Explorar el Código

Merge branch 'master' into hotfix/issue2173

Aleos hace 7 años
padre
commit
3b31b31605
Se han modificado 100 ficheros con 7695 adiciones y 3477 borrados
  1. 4 4
      .travis.yml
  2. 2 2
      3rdparty/yaml-cpp/src/contrib/graphbuilderadapter.h
  3. 4 4
      3rdparty/yaml-cpp/src/singledocparser.cpp
  4. 3 3
      Makefile.in
  5. 0 52
      conf/battle/client.conf
  6. 4 0
      conf/battle/feature.conf
  7. 1 2
      conf/help.txt
  8. 0 6
      conf/login_athena.conf
  9. 5 0
      conf/msg_conf/char_msg.conf
  10. 8 3
      conf/msg_conf/map_msg.conf
  11. 1 2
      conf/msg_conf/map_msg_chn.conf
  12. 1 2
      conf/msg_conf/map_msg_frn.conf
  13. 1 2
      conf/msg_conf/map_msg_idn.conf
  14. 1 2
      conf/msg_conf/map_msg_rus.conf
  15. 1 2
      conf/msg_conf/map_msg_tha.conf
  16. 78 0
      db/import-tmpl/achievement_db.yml
  17. 0 35
      db/import-tmpl/packet_db.txt
  18. 0 2675
      db/packet_db.txt
  19. 2407 0
      db/pre-re/achievement_db.yml
  20. 2407 0
      db/re/achievement_db.yml
  21. 9 9
      db/re/item_db.txt
  22. 11 1
      db/re/mob_db.txt
  23. 102 0
      doc/achievements.txt
  24. 4 4
      doc/atcommands.txt
  25. 27 8
      doc/packet_interserv.txt
  26. 89 14
      doc/script_commands.txt
  27. 2 1
      npc/re/guides/navigation.txt
  28. 278 0
      npc/re/other/achievements.txt
  29. 1 0
      npc/re/scripts_athena.conf
  30. 1 0
      rAthena.sln
  31. 9 9
      sql-files/item_db_re.sql
  32. 24 0
      sql-files/main.sql
  33. 11 1
      sql-files/mob_db_re.sql
  34. 0 1
      sql-files/upgrades/upgrade_20140104.sql
  35. 0 20
      sql-files/upgrades/upgrade_20140114.sql
  36. 0 21
      sql-files/upgrades/upgrade_20140205.sql
  37. 0 1
      sql-files/upgrades/upgrade_20140523.sql
  38. 0 118
      sql-files/upgrades/upgrade_20140612.sql
  39. 0 12
      sql-files/upgrades/upgrade_20140612_log.sql
  40. 0 6
      sql-files/upgrades/upgrade_20140616.sql
  41. 0 1
      sql-files/upgrades/upgrade_20140627.sql
  42. 0 1
      sql-files/upgrades/upgrade_20140713_log.sql
  43. 0 7
      sql-files/upgrades/upgrade_20140723.sql
  44. 0 1
      sql-files/upgrades/upgrade_20140822.sql
  45. 0 1
      sql-files/upgrades/upgrade_20140826.sql
  46. 0 1
      sql-files/upgrades/upgrade_20140915.sql
  47. 0 1
      sql-files/upgrades/upgrade_20140915_log.sql
  48. 0 1
      sql-files/upgrades/upgrade_20150103_log.sql
  49. 0 6
      sql-files/upgrades/upgrade_20150131.sql
  50. 0 6
      sql-files/upgrades/upgrade_20150211_skillset.sql
  51. 0 12
      sql-files/upgrades/upgrade_20150327_market.sql
  52. 0 9
      sql-files/upgrades/upgrade_20150408.sql
  53. 0 1
      sql-files/upgrades/upgrade_20150408_log.sql
  54. 0 68
      sql-files/upgrades/upgrade_20150619.sql
  55. 0 1
      sql-files/upgrades/upgrade_20150619_log.sql
  56. 0 1
      sql-files/upgrades/upgrade_20150804_log.sql
  57. 0 1
      sql-files/upgrades/upgrade_20150828.sql
  58. 0 66
      sql-files/upgrades/upgrade_20150831.sql
  59. 0 1
      sql-files/upgrades/upgrade_20150917_log.sql
  60. 0 19
      sql-files/upgrades/upgrade_20151230_log.sql
  61. 25 0
      sql-files/upgrades/upgrade_20170407.sql
  62. 2 0
      src/char/char-server.vcxproj
  63. 6 0
      src/char/char-server.vcxproj.filters
  64. 23 8
      src/char/char.cpp
  65. 1 1
      src/char/char.h
  66. 25 24
      src/char/char_clif.c
  67. 4 10
      src/char/char_logif.c
  68. 2 4
      src/char/char_mapif.c
  69. 344 0
      src/char/int_achievement.c
  70. 9 0
      src/char/int_achievement.h
  71. 1 1
      src/char/int_guild.c
  72. 6 2
      src/char/int_mail.c
  73. 1 1
      src/char/int_mail.h
  74. 47 11
      src/char/int_party.c
  75. 3 1
      src/char/inter.c
  76. 20 10
      src/common/Makefile.in
  77. 8 4
      src/common/core.cpp
  78. 2 2
      src/common/ers.c
  79. 1 1
      src/common/ers.h
  80. 1 0
      src/common/mapindex.h
  81. 17 22
      src/common/mmo.h
  82. 10 0
      src/common/sql.c
  83. 7 0
      src/common/sql.h
  84. 0 53
      src/common/utils.c
  85. 0 2
      src/common/utils.h
  86. 57 5
      src/common/yamlwrapper.cpp
  87. 7 1
      src/common/yamlwrapper.h
  88. 5 6
      src/config/core.h
  89. 63 0
      src/config/packets.h
  90. 13 0
      src/custom/defines_post.h
  91. 13 0
      src/custom/defines_pre.h
  92. 0 14
      src/login/login.cpp
  93. 0 4
      src/login/login.h
  94. 6 8
      src/login/loginchrif.c
  95. 28 39
      src/login/loginclif.c
  96. 15 6
      src/map/Makefile.in
  97. 1268 0
      src/map/achievement.c
  98. 135 0
      src/map/achievement.h
  99. 16 8
      src/map/atcommand.c
  100. 8 2
      src/map/battle.c

+ 4 - 4
.travis.yml

@@ -27,14 +27,15 @@ before_script:
   - mysql -u $DB_ROOT -e "GRANT ALL ON *.* TO '$DB_USER'@'$DB_HOST' IDENTIFIED BY '$DB_PASS';"
   - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
   - sudo apt-get update -q
-  - sudo apt-get install gcc-4.8 -y
-  - sudo apt-get install g++-4.8 -y
+  - sudo apt-get install gcc-5 -y
+  - sudo apt-get install g++-5 -y
+  - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 1
+  - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 1
 
 script:
   - ./configure $CONFIGURE_FLAGS
   - make clean
   - make server
-  - 'echo packet_db_ver: $PACKETDBVER >> db/import/packet_db.txt'
   - ./map-server --run-once
 
 env:
@@ -44,7 +45,6 @@ env:
     - DB_NAME="ragnarok"
     - DB_USER="ragnarok"
     - DB_PASS="ragnarok"
-    - PACKETDBVER=45
   matrix:
     - CONFIGURE_FLAGS="--enable-prere=no --enable-vip=no --enable-buildbot=yes"
     - CONFIGURE_FLAGS="--enable-prere=yes --enable-vip=no --enable-buildbot=yes"

+ 2 - 2
3rdparty/yaml-cpp/src/contrib/graphbuilderadapter.h

@@ -50,8 +50,8 @@ class GraphBuilderAdapter : public EventHandler {
   struct ContainerFrame {
     ContainerFrame(void* pSequence)
         : pContainer(pSequence), pPrevKeyNode(&sequenceMarker) {}
-    ContainerFrame(void* pMap, void* pPrevKeyNode)
-        : pContainer(pMap), pPrevKeyNode(pPrevKeyNode) {}
+    ContainerFrame(void* pMap, void* pPrevKeyNode_)
+        : pContainer(pMap), pPrevKeyNode(pPrevKeyNode_) {}
 
     void* pContainer;
     void* pPrevKeyNode;

+ 4 - 4
3rdparty/yaml-cpp/src/singledocparser.cpp

@@ -166,10 +166,10 @@ void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) {
 
     // check for null
     if (!m_scanner.empty()) {
-      const Token& token = m_scanner.peek();
-      if (token.type == Token::BLOCK_ENTRY ||
-          token.type == Token::BLOCK_SEQ_END) {
-        eventHandler.OnNull(token.mark, NullAnchor);
+      const Token& token_ = m_scanner.peek();
+      if (token_.type == Token::BLOCK_ENTRY ||
+          token_.type == Token::BLOCK_SEQ_END) {
+        eventHandler.OnNull(token_.mark, NullAnchor);
         continue;
       }
     }

+ 3 - 3
Makefile.in

@@ -5,10 +5,10 @@ OMAP=@OMAP@
 ifeq ($(HAVE_MYSQL),yes)
 	ALL_DEPENDS=server tools
 	SERVER_DEPENDS=common login char map import
-	COMMON_DEPENDS=mt19937ar libconfig
+	COMMON_DEPENDS=mt19937ar libconfig yaml-cpp
 	LOGIN_DEPENDS=mt19937ar libconfig common
 	CHAR_DEPENDS=mt19937ar libconfig common
-	MAP_DEPENDS=mt19937ar libconfig common
+	MAP_DEPENDS=mt19937ar libconfig common yaml-cpp
 else
 	ALL_DEPENDS=needs_mysql
 	SERVER_DEPENDS=needs_mysql
@@ -93,7 +93,7 @@ help:
 	@echo "'common'      - builds object files used for the three servers"
 	@echo "'mt19937ar'   - builds object file of Mersenne Twister MT19937"
 	@echo "'libconfig'   - builds object files of libconfig"
-	@echo "'libconfig'   - builds object files of yaml-cpp"
+	@echo "'yaml-cpp'    - builds object files of yaml-cpp"
 	@echo "'login'       - builds login server"
 	@echo "'char'        - builds char server"
 	@echo "'map'         - builds map server"

+ 0 - 52
conf/battle/client.conf

@@ -9,58 +9,6 @@
 //         assume unit types (1: Pc, 2: Mob, 4: Pet, 8: Homun, 16: Mercenary)
 //--------------------------------------------------------------
 
-// Set here which client version do you accept. Add all values of clients:
-// Clients older than accepted versions, and versions not set to 'accepted'
-// here will be rejected when logging in
-// 0x00000001: Clients older than 2004-09-06aSakray (packet versions 5-9)
-// 0x00000002: 2004-09-06	aSakexe		(version 10)
-// 0x00000004: 2004-09-20	aSakexe		(version 11)
-// 0x00000008: 2004-10-05	aSakexe		(version 12)
-// 0x00000010: 2004-10-25	aSakexe		(version 13)
-// 0x00000020: 2004-11-29	aSakexe		(version 14)
-// 0x00000040: 2005-01-10	bSakexe		(version 15)
-// 0x00000080: 2005-05-09	aSakexe		(version 16)
-// 0x00000100: 2005-06-28	aSakexe		(version 17)
-// 0x00000200: 2005-07-18	aSakexe		(version 18)
-// 0x00000400: 2005-07-19	bSakexe		(version 19)
-// 0x00000800: 2006-03-27	aSakexe		(version 20)
-// 0x00001000: 2007-01-08	aSakexe		(version 21)
-// 0x00002000: 2007-02-12	aSakexe		(version 22)
-// 0x00004000: 2008-09-10	aSakexe		(version 23)
-// 0x00008000: 2008-08-27	aRagexeRE	(version 24)
-// 0x00010000: 2008-09-10	aRagexeRE	(version 25)
-// 0x00020000: 2010-11-24	aRagexeRE	(version 26)
-// 0x00040000: 2011-10-05	aRagexeRE	(version 27)
-// 0x00080000: 2011-11-02	aRagexe		(version 28)
-// 0x00100000: 2012-03-07	fRagexeRE	(version 29)
-// 0x00200000: 2012-04-10	aRagexeRE	(version 30)
-// 0x00400000: 2012-04-18	aRagexeRE	(version 31)
-// 0x00800000: 2012-06-18	unknow 		(version 32)
-// 0x01000000: 2012-07-02	aRagexeRE	(version 33)
-// 0x02000000: 2013-03-20	Ragexe		(version 34)
-// 0x04000000: 2013-05-15	aRagexe		(version 35)
-// 0x08000000: 2013-05-22	Ragexe		(version 36)
-// 0x10000000: 2013-05-29	Ragexe		(version 37)
-// 0x20000000: 2013-06-05	Ragexe		(version 38)
-// 0x40000000: 2013-06-12	Ragexe		(version 39)
-// default value: 0x7FFFFFFF			(all clients/versions [5;39])
-packet_ver_flag: 0x7FFFFFFF
-
-// 0x00000001: 2013-06-18	Ragexe		(version 40)
-// 0x00000002: 2013-06-26	Ragexe		(version 41)
-// 0x00000004: 2013-07-03	Ragexe		(version 42)
-// 0x00000008: 2013-07-10	Ragexe		(version 43)
-// 0x00000010: 2013-07-17	Ragexe		(version 44)
-// 0x00000020: 2013-08-07	Ragexe		(version 45)
-// 0x00000040: 2013-12-23	Ragexe		(version 46)
-// 0x00000080: ????
-// 0x00000100: ????
-// 0x00000200: ????
-// 0x00000400: 2014-10-16	Ragexe		(version 50)
-// 0x00000800: 2014-10-22	Ragexe		(version 51)
-// default value: 0x7FFFFFFF			(all clients/versions [41;72])
-packet_ver_flag2: 0x7FFFFFFF
-
 // Minimum delay between whisper/global/party/guild messages (in ms)
 // Messages that break this threshold are silently omitted. 
 min_chat_delay: 0

+ 4 - 0
conf/battle/feature.conf

@@ -63,3 +63,7 @@ feature.autotrade_open_delay: 5000
 // Requires: 2014-10-22bRagexe or later
 // Off by default while test version is out; enable at your own risk.
 feature.roulette: off
+
+// Achievement (Note 1)
+// Requires: 2015-05-13aRagexe or later
+feature.achievement: on

+ 1 - 2
conf/help.txt

@@ -42,7 +42,7 @@ go: "Params: <city name|number>\n" "Warps you to a city.\n"
 	"  -1: (Memo point 0)  16: prison/jail     33: malangdo island\n"
 	"   0: prontera              17: jawaii             34: malaya port\n"
 	"   1: morocc                18: ayothaya       35: eclage\n"
-	"   2: geffen                  19: einbroch\n"
+	"   2: geffen                  19: einbroch       36: lasagna\n"
 	"   3: payon                  20: lighthalzen\n"
 	"   4: alberta                 21: einbech\n"
 	"   5: izlude                   22: hugel\n"
@@ -310,7 +310,6 @@ reloaditemdb: "Reload item database."
 reloadmobdb: "Reload monster database."
 reloadmotd: "Reload Message of the Day."
 reloadmsgconf: "Reload message configuration."
-reloadpacketdb: "Reload packet database."
 reloadpcdb: "Reload player settings."
 reloadquestdb: "Reload quest database."
 reloadscript: "Reload all scripts."

+ 0 - 6
conf/login_athena.conf

@@ -106,12 +106,6 @@ vip_char_increase: -1
 // 0 or more: new accounts automatically expire after the given value, in seconds
 start_limited_time: -1
 
-// Check the clientversion field set in clientinfo.xml?
-check_client_version: no
-
-// What version is allowed to connect? (if the option above is enabled)
-client_version_to_connect: 20
-
 // Store passwords as MD5 hashes instead of plain text?
 // NOTE: Will not work with clients that use <passwordencrypt>
 use_MD5_passwords: no

+ 5 - 0
conf/msg_conf/char_msg.conf

@@ -157,3 +157,8 @@
 224: -- Character Details --
 225: [Slot/CID: %d/%d] %s | %s | Level: %d/%d | %s
 226: This account doesn't have characters.
+
+// Achievements
+227: GM
+228: Achievement Reward Mail
+229: [%s] Achievement Reward.

+ 8 - 3
conf/msg_conf/map_msg.conf

@@ -825,7 +825,13 @@
 769: %s %s has been banned.
 770: %s %s has been unbanned.
 
-//771-899 free
+//@reloadachievementdb
+771: Achievement database has been reloaded.
+
+// Achievements
+772: Achievements are disabled.
+
+//773-899 free
 
 //------------------------------------
 // More atcommands message
@@ -1615,8 +1621,7 @@
 1475: ---- My Channels ----
 1476: You have not joined any channels.
 
-// @reloadpacketdb
-1477: Packet database has been reloaded.
+//1477 free
 
 // @partysharelvl
 1478: Party share level range has been changed successfully.

+ 1 - 2
conf/msg_conf/map_msg_chn.conf

@@ -1469,8 +1469,7 @@
 1475: ---- 我的頻道 ----
 1476: 你沒有加入任何的頻道
 
-// @reloadpacketdb
-1477: 完成重載封包數據庫.
+//1477 free
 
 // @partysharelvl
 1478: 隊伍經驗均分的等級間距已成功變更。

+ 1 - 2
conf/msg_conf/map_msg_frn.conf

@@ -1480,8 +1480,7 @@
 1475: ---- Canaux rejoins ----
 1476: Vous n'avez rejoins aucun canal.
 
-// @reloadpacketdb
-1477: Base de donnée des 'Packets' rechargée.
+//1477 free
 
 // @partysharelvl
 1478: Différence de niveau pour le partage en équipe changé.

+ 1 - 2
conf/msg_conf/map_msg_idn.conf

@@ -1571,8 +1571,7 @@
 1475: ---- Channel yang diikuti ----
 1476: Kamu tidak bergabung ke channel manapun saat ini.
 
-// @reloadpacketdb
-1477: Database paket telah dimuat ulang.
+//1477 free
 
 // @partysharelvl
 1478: Jarak level dalam party share telah diubah dengan sukses.

+ 1 - 2
conf/msg_conf/map_msg_rus.conf

@@ -1480,8 +1480,7 @@
 1475: ---- Мои каналы ----
 1476: Вы не присоединились ни к одному каналу.
 
-// @reloadpacketdb
-1477: База данных пакетов была перезагружена.
+//1477 free
 
 // @partysharelvl
 1478: Диапазон уровней разделения опыта между участниками группы успешно изменен.

+ 1 - 2
conf/msg_conf/map_msg_tha.conf

@@ -1473,8 +1473,7 @@
 1475: ---- Channels ·�ט©�¹���ט ----
 1476: ¤�³ה�טה´י���טד¹ channels ד´א��.
 
-// @reloadpacketdb
-1477: °�¹¢י���� Packet ה´י¶��ג��´ד��טא���÷�י��.
+//1477 free
 
 // @partysharelvl
 1478: ��´�÷ Level �����÷���ב×�ל ה´י¶��»��÷א»��ט�¹א���÷�י��ב�י�.

+ 78 - 0
db/import-tmpl/achievement_db.yml

@@ -0,0 +1,78 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2017 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 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/>.
+#
+###########################################################################
+# Custom Achievement Database
+###########################################################################
+#
+# Achievement Settings
+#
+###########################################################################
+# Id - Unique achievement ID.
+###########################################################################
+# Group - Achievement group type. Each achievement type calls a specific
+# objective check.
+# Valid groups:
+#  AG_ADD_FRIEND
+#  AG_ADVENTURE
+#  AG_BABY
+#  AG_BATTLE
+#  AG_CHATTING
+#  AG_CHATTING_COUNT
+#  AG_CHATTING_CREATE
+#  AG_CHATTING_DYING
+#  AG_EAT
+#  AG_GET_ITEM
+#  AG_GET_ZENY
+#  AG_GOAL_ACHIEVE
+#  AG_GOAL_LEVEL
+#  AG_GOAL_STATUS
+#  AG_HEAR
+#  AG_JOB_CHANGE
+#  AG_MARRY
+#  AG_PARTY
+#  AG_ENCHANT_FAIL
+#  AG_ENCHANT_SUCCESS
+#  AG_SEE
+#  AG_SPEND_ZENY
+#  AG_TAMING
+###########################################################################
+# Name - Achievement name. Used when sending rewards through RODEX.
+###########################################################################
+# Target - A list of monster ID and count values that the achievement
+# requires. The target count can also be used for achievements that keep
+# a counter while not being related to monster kills.
+# Capped at MAX_ACHIEVEMENT_OBJECTIVES.
+###########################################################################
+# Condition - A conditional statement that must be met for the achievement
+# to be considered complete.
+###########################################################################
+# Map - A map name that is used for the AG_CHATTING type which increments
+# the counter based on the player's map.
+###########################################################################
+# Dependent: - A list of achievement IDs that need to be completed before
+# this achievement is considered complete.
+###########################################################################
+# Reward - A list of rewards that are given on completion. All fields are
+# optional.
+#   ItemId: Item ID
+#   Amount:  Amount of Item ID (default 1)
+#   Script: Bonus Script
+#   TitleId: Title ID
+###########################################################################
+# Score - Achievement points that are given on completion.
+###########################################################################

+ 0 - 35
db/import-tmpl/packet_db.txt

@@ -1,35 +0,0 @@
-// Client<->Map Packet Database
-//
-// Structure of Database:
-// PacketType,PacketLength[,Name,FieldIndex1:FieldIndex2:FieldIndex3:...]
-//
-// 01. PacketType       ID of the packet.
-// 02. PacketLength     Length of the packet. If 0, packet is disabled in current packet version. If -1, packet has variable size.
-// 03. Name             Name of the packet parser function (optional, for incoming packets only).
-// 04. FieldIndex       Specifies the offset of a packet field in bytes from the begin of the packet (only specified when Name is given).
-//                      Can be 0, when the layout is not known.
-// ...
-//
-// NOTE: Up to MAX_PACKET_POS (typically 20) field indexes may be used.
-//
-// The packet database allows you to add support for new clients,
-// because packets change every release.
-//
-// Note: Every packet version needs a wanttoconnection specification, since
-// that is the packet used to identify a client's version.
-// If multiple versions have the same connection packet, the higher version
-// will be used (unless the lower one is specified as the default)
-//
-// Incoming packets have their parser function and layout specified, which enables
-// them for the current and all higher versions, unless explicitely disabled.
-//
-// Outgoing packets must be specified in order to enable them for the current
-// and all higher versions, unless explicitely disabled. Packets that are not
-// enabled for a packet version are silently discarded when sent as multicast.
-//
-// Every packet version inherits packet definitions from the previous (lower)
-// packet version.
-//
-// Main packet version of the DB to use (default = max available version)
-// Client detection is faster when all clients use this version.
-// Version 23 is the latest Sakexe (above versions are for Renewal clients)

+ 0 - 2675
db/packet_db.txt

@@ -1,2675 +0,0 @@
-// Client<->Map Packet Database
-//
-// Structure of Database:
-// PacketType,PacketLength[,Name,FieldIndex1:FieldIndex2:FieldIndex3:...]
-//
-// 01. PacketType       ID of the packet.
-// 02. PacketLength     Length of the packet. If 0, packet is disabled in current packet version. If -1, packet has variable size.
-// 03. Name             Name of the packet parser function (optional, for incoming packets only).
-// 04. FieldIndex       Specifies the offset of a packet field in bytes from the begin of the packet (only specified when Name is given).
-//                      Can be 0, when the layout is not known.
-// ...
-//
-// NOTE: Up to MAX_PACKET_POS (typically 20) field indexes may be used.
-//
-// The packet database allows you to add support for new clients,
-// because packets change every release.
-//
-// Note: Every packet version needs a wanttoconnection specification, since
-// that is the packet used to identify a client's version.
-// If multiple versions have the same connection packet, the higher version
-// will be used (unless the lower one is specified as the default)
-//
-// Incoming packets have their parser function and layout specified, which enables
-// them for the current and all higher versions, unless explicitely disabled.
-//
-// Outgoing packets must be specified in order to enable them for the current
-// and all higher versions, unless explicitely disabled. Packets that are not
-// enabled for a packet version are silently discarded when sent as multicast.
-//
-// Every packet version inherits packet definitions from the previous (lower)
-// packet version.
-//
-// Main packet version of the DB to use (default = max available version)
-// Client detection is faster when all clients use this version.
-// Version 23 is the latest Sakexe (above versions are for Renewal clients)
-//
-// packet_keys values are default value for each packet version, if no value
-// or value is 'default' in packet_keys_use, server will uses default keys
-// according to used packet_db_ver. packet_keys_use is user-defined keys.
-// Maximum key value is 0x7FFFFFFF.
-// NOTE: Keys won't be reloaded, initialized on first load only.
-//
-//packet_db_ver: 46
-packet_db_ver: default
-packet_keys_use: default
-
-packet_ver: 5
-0x0064,55
-0x0065,17
-0x0066,6
-0x0067,37
-0x0068,46
-0x0069,-1
-0x006a,23
-0x006b,-1
-0x006c,3
-0x006d,108
-0x006e,3
-0x006f,2
-0x0070,6
-0x0071,28
-0x0072,19,wanttoconnection,2:6:10:14:18
-0x0073,11
-0x0074,3
-0x0075,-1
-0x0076,9
-0x0077,5
-0x0078,54
-0x0079,53
-0x007a,58
-0x007b,60
-0x007c,41
-0x007d,2,loadendack,0
-0x007e,6,ticksend,2
-0x007f,6
-0x0080,7
-0x0081,3
-0x0082,2
-0x0083,2
-0x0084,2
-0x0085,5,walktoxy,2
-0x0086,16
-0x0087,12
-0x0088,10
-0x0089,7,actionrequest,2:6
-0x008a,29
-0x008b,2
-0x008c,-1,globalmessage,2:4
-0x008d,-1
-0x008e,-1
-//0x008f,-1
-0x0090,7,npcclicked,2:6
-0x0091,22
-0x0092,28
-0x0093,2
-0x0094,6,getcharnamerequest,2
-0x0095,30
-0x0096,-1,wis,2:4:28
-0x0097,-1
-0x0098,3
-0x0099,-1,broadcast,2:4
-0x009a,-1
-0x009b,5,changedir,2:4
-0x009c,9
-0x009d,17
-0x009e,17
-0x009f,6,takeitem,2
-0x00a0,23
-0x00a1,6
-0x00a2,6,dropitem,2:4
-0x00a3,-1
-0x00a4,-1
-0x00a5,-1
-0x00a6,-1
-0x00a7,8,useitem,2:4
-0x00a8,7
-0x00a9,6,equipitem,2:4
-0x00aa,7,ZC_WEAR_EQUIP_ACK,2:4:6
-0x00ab,4,unequipitem,2
-0x00ac,7
-//0x00ad,-1
-0x00ae,-1
-0x00af,6
-0x00b0,8
-0x00b1,8
-0x00b2,3,restart,2
-0x00b3,3
-0x00b4,-1
-0x00b5,6
-0x00b6,6
-0x00b7,-1
-0x00b8,7,npcselectmenu,2:6
-0x00b9,6,npcnextclicked,2
-0x00ba,2
-0x00bb,5,statusup,2:4
-0x00bc,6
-0x00bd,44
-0x00be,5
-0x00bf,3,emotion,2
-0x00c0,7
-0x00c1,2,howmanyconnections,0
-0x00c2,6
-0x00c3,8
-0x00c4,6
-0x00c5,7,npcbuysellselected,2:6
-0x00c6,-1
-0x00c7,-1
-0x00c8,-1,npcbuylistsend,2:4
-0x00c9,-1,npcselllistsend,2:4
-0x00ca,3
-0x00cb,3
-0x00cc,6,gmkick,2
-0x00cd,3
-0x00ce,2,killall,0
-0x00cf,27,wisexin,2:26
-0x00d0,3,wisall,2
-0x00d1,4
-0x00d2,4
-0x00d3,2,wisexlist,0
-0x00d4,-1
-0x00d5,-1,createchatroom,2:4:6:7:15
-0x00d6,3
-0x00d7,-1
-0x00d8,6
-0x00d9,14,chataddmember,2:6
-0x00da,3
-0x00db,-1
-0x00dc,28
-0x00dd,29
-0x00de,-1,chatroomstatuschange,2:4:6:7:15
-0x00df,-1
-0x00e0,30,changechatowner,2:6
-0x00e1,30
-0x00e2,26,kickfromchat,2
-0x00e3,2,chatleave,0
-0x00e4,6,traderequest,2
-0x00e5,26
-0x00e6,3,tradeack,2
-0x00e7,3
-0x00e8,8,tradeadditem,2:4
-0x00e9,19
-0x00ea,5
-0x00eb,2,tradeok,0
-0x00ec,3
-0x00ed,2,tradecancel,0
-0x00ee,2
-0x00ef,2,tradecommit,0
-0x00f0,3
-0x00f1,2
-0x00f2,6
-0x00f3,8,movetokafra,2:4
-0x00f4,21
-0x00f5,8,movefromkafra,2:4
-0x00f6,8
-0x00f7,2,closekafra,0
-0x00f8,2
-0x00f9,26,createparty,2
-0x00fa,3
-0x00fb,-1
-0x00fc,6,partyinvite,2
-0x00fd,27
-0x00fe,30
-0x00ff,10,replypartyinvite,2:6
-0x0100,2,leaveparty,0
-0x0101,6
-0x0102,6,partychangeoption,2
-0x0103,30,removepartymember,2:6
-0x0104,79
-0x0105,31
-0x0106,10
-0x0107,10
-0x0108,-1,partymessage,2:4
-0x0109,-1
-0x010a,4
-0x010b,6
-0x010c,6
-0x010d,2
-0x010e,11
-0x010f,-1
-0x0110,10
-0x0111,39
-0x0112,4,skillup,2
-0x0113,10,useskilltoid,2:4:6
-0x0114,31
-0x0115,35
-0x0116,10,useskilltopos,2:4:6:8
-0x0117,18
-0x0118,2,stopattack,0
-0x0119,13
-0x011a,15
-0x011b,20,useskillmap,2:4
-0x011c,68
-0x011d,2,requestmemo,0
-0x011e,3
-0x011f,16
-0x0120,6
-0x0121,14
-0x0122,-1
-0x0123,-1
-0x0124,21
-0x0125,8
-0x0126,8,putitemtocart,2:4
-0x0127,8,getitemfromcart,2:4
-0x0128,8,movefromkafratocart,2:4
-0x0129,8,movetokafrafromcart,2:4
-0x012a,2,removeoption,0
-0x012b,2
-0x012c,3
-0x012d,4
-0x012e,2,closevending,0
-0x012f,-1,openvending,2:4:0:84
-0x0130,6,vendinglistreq,2
-0x0131,86
-0x0132,6
-0x0133,-1
-0x0134,-1,purchasereq,2:4:8
-0x0135,7
-0x0136,-1
-0x0137,6
-0x0138,3
-0x0139,16
-0x013a,4
-0x013b,4
-0x013c,4
-0x013d,6
-0x013e,24
-0x013f,26,itemmonster,2
-0x0140,22,mapmove,2:18:20
-0x0141,14
-0x0142,6
-0x0143,10,npcamountinput,2:6
-0x0144,23
-0x0145,19
-0x0146,6,npccloseclicked,2
-0x0147,39
-0x0148,8
-0x0149,9,gmreqnochat,2:6:7
-0x014a,6
-0x014b,27
-0x014c,-1
-0x014d,2,guildcheckmaster,0
-0x014e,6
-0x014f,6,guildrequestinfo,2
-0x0150,110
-0x0151,6,guildrequestemblem,2
-0x0152,-1
-0x0153,-1,guildchangeemblem,2:4
-0x0154,-1
-0x0155,-1,guildchangememberposition,2:4
-0x0156,-1
-0x0157,6
-0x0158,-1
-0x0159,54,guildleave,2:6:10:14
-0x015a,66
-0x015b,54,guildexpulsion,2:6:10:14
-0x015c,90
-0x015d,42,guildbreak,2
-0x015e,6
-0x015f,42
-0x0160,-1
-0x0161,-1,guildchangepositioninfo,2:4
-0x0162,-1
-0x0163,-1
-0x0164,-1
-0x0165,30,createguild,2:6
-0x0166,-1
-0x0167,3
-0x0168,14,guildinvite,2:6:10
-0x0169,3
-0x016a,30
-0x016b,10,guildreplyinvite,2:6
-0x016c,43
-0x016d,14
-0x016e,186,guildchangenotice,2:6:66
-0x016f,182
-0x0170,14,guildrequestalliance,2:6:10
-0x0171,30
-0x0172,10,guildreplyalliance,2:6
-0x0173,3
-0x0174,-1
-0x0175,6
-0x0176,106
-0x0177,-1
-0x0178,4,itemidentify,2
-0x0179,5
-0x017a,4,usecard,2
-0x017b,-1
-0x017c,6,insertcard,2:4
-0x017d,7
-0x017e,-1,guildmessage,2:4
-0x017f,-1
-0x0180,6,guildopposition,2
-0x0181,3
-0x0182,106
-0x0183,10,guilddelalliance,2:6
-0x0184,10
-0x0185,34
-//0x0186,-1
-0x0187,6
-0x0188,8
-0x0189,4
-0x018a,4,quitgame,2
-0x018b,4
-0x018c,29
-0x018d,-1
-0x018e,10,producemix,2:4:6:8
-0x018f,6
-0x0190,90,useskilltoposinfo,2:4:6:8:10
-0x0191,86
-0x0192,24
-0x0193,6,solvecharname,2
-0x0194,30
-0x0195,102
-0x0196,9
-0x0197,4,resetchar,2
-0x0198,8,changemaptype,2:4:6
-0x0199,4
-0x019a,14
-0x019b,10
-0x019c,-1,localbroadcast,2:4
-0x019d,6,gmhide,2
-0x019e,2
-0x019f,6,catchpet,2
-0x01a0,3
-0x01a1,3,petmenu,2
-0x01a2,35
-0x01a3,5
-0x01a4,11
-0x01a5,26,changepetname,2
-0x01a6,-1
-0x01a7,4,selectegg,2
-0x01a8,4
-0x01a9,6,sendemotion,2
-0x01aa,10
-0x01ab,12
-0x01ac,6
-0x01ad,-1
-0x01ae,4,selectarrow,2
-0x01af,4,changecart,2
-0x01b0,11
-0x01b1,7
-0x01b2,-1,openvending,2:4:84:85
-0x01b3,67
-0x01b4,12
-0x01b5,18
-0x01b6,114
-0x01b7,6
-0x01b8,3
-0x01b9,6
-0x01ba,26,remove,2
-0x01bb,26,shift,2
-0x01bc,26,recall,2
-0x01bd,26,summon,2
-0x01be,2
-0x01bf,3
-0x01c0,2
-0x01c1,14
-0x01c2,10
-0x01c3,-1
-0x01c4,22
-0x01c5,22
-0x01c6,4
-0x01c7,2
-0x01c8,13
-0x01c9,97
-//0x01ca,-1
-0x01cb,9
-0x01cc,9
-0x01cd,30
-0x01ce,6,autospell,2
-0x01cf,28
-0x01d0,8
-0x01d1,14
-0x01d2,10
-0x01d3,35
-0x01d4,6
-0x01d5,-1,npcstringinput,2:4:8
-0x01d6,4
-0x01d7,11
-0x01d8,54
-0x01d9,53
-0x01da,60
-0x01db,2
-0x01dc,-1
-0x01dd,47
-0x01de,33
-0x01df,6,gmreqaccname,2
-0x01e0,30
-0x01e1,8
-0x01e2,34
-0x01e3,14
-0x01e4,2
-0x01e5,6
-0x01e6,26
-0x01e7,2,sndoridori,0
-0x01e8,28,createparty2,2:26:27
-0x01e9,81
-0x01ea,6
-0x01eb,10
-0x01ec,26
-0x01ed,2,snexplosionspirits,0
-0x01ee,-1
-0x01ef,-1
-0x01f0,-1
-0x01f1,-1
-0x01f2,20
-0x01f3,10
-0x01f4,32
-0x01f5,9
-0x01f6,34
-0x01f7,14,adoptreply,2:6:10
-0x01f8,2
-0x01f9,6,adoptrequest,2
-0x01fa,48
-0x01fb,56
-0x01fc,-1
-0x01fd,4,repairitem,2
-0x01fe,5
-0x01ff,10
-0x0200,26
-0x0201,-1
-0x0202,26,friendslistadd,2
-0x0203,10,friendslistremove,2:6
-0x0204,18
-0x0205,26
-0x0206,11
-0x0207,34
-0x0208,11,friendslistreply,2:6:10
-0x0209,36
-0x020a,10
-//0x020b,-1
-//0x020c,-1
-0x020d,-1
-0x8b3,-1
-0x8d6,6,ZC_CLEAR_DIALOG,2
-
-//2004-07-05aSakexe
-packet_ver: 6
-0x0072,22,wanttoconnection,5:9:13:17:21
-0x0085,8,walktoxy,5
-0x00a7,13,useitem,5:9
-0x0113,15,useskilltoid,4:9:11
-0x0116,15,useskilltopos,4:9:11:13
-0x0190,95,useskilltoposinfo,4:9:11:13:15
-0x0208,14,friendslistreply,2:6:10
-0x020e,24
-
-//2004-07-13aSakexe
-packet_ver: 7
-0x0072,39,wanttoconnection,12:22:30:34:38
-0x0085,9,walktoxy,6
-0x009b,13,changedir,5:12
-0x009f,10,takeitem,6
-0x00a7,17,useitem,6:13
-0x0113,19,useskilltoid,7:9:15
-0x0116,19,useskilltopos,7:9:15:17
-0x0190,99,useskilltoposinfo,7:9:15:17:19
-
-//2004-07-26aSakexe
-packet_ver: 8
-0x0072,14,dropitem,5:12
-0x007e,33,wanttoconnection,12:18:24:28:32
-0x0085,20,useskilltoid,7:12:16
-0x0089,15,getcharnamerequest,11
-0x008c,23,useskilltopos,3:6:17:21
-0x0094,10,takeitem,6
-0x009b,6,walktoxy,3
-0x009f,13,changedir,5:12
-0x00a2,103,useskilltoposinfo,3:6:17:21:23
-0x00a7,12,solvecharname,8
-0x00f3,-1,globalmessage,2:4
-0x00f5,17,useitem,6:12
-0x00f7,10,ticksend,6
-0x0113,16,movetokafra,5:12
-0x0116,2,closekafra,0
-0x0190,26,movefromkafra,10:22
-0x0193,9,actionrequest,3:8
-
-//2004-08-09aSakexe
-packet_ver: 9
-0x0072,17,dropitem,8:15
-0x007e,37,wanttoconnection,9:21:28:32:36
-0x0085,26,useskilltoid,11:18:22
-0x0089,12,getcharnamerequest,8
-0x008c,40,useskilltopos,5:15:29:38
-0x0094,13,takeitem,9
-0x009b,15,walktoxy,12
-0x009f,12,changedir,7:11
-0x00a2,120,useskilltoposinfo,5:15:29:38:40
-0x00a7,11,solvecharname,7
-0x00f5,24,useitem,9:20
-0x00f7,13,ticksend,9
-0x0113,23,movetokafra,5:19
-0x0190,26,movefromkafra,11:22
-0x0193,18,actionrequest,7:17
-
-//2004-08-16aSakexe
-0x0212,26,rc,2
-0x0213,26,check,2
-0x0214,42
-
-//2004-08-17aSakexe
-0x020f,10,pvpinfo,2:6
-0x0210,22
-
-//2004-09-06aSakexe
-packet_ver: 10
-0x0072,20,useitem,9:20
-0x007e,19,movetokafra,3:15
-0x0085,23,actionrequest,9:22
-0x0089,9,walktoxy,6
-0x008c,105,useskilltoposinfo,10:14:18:23:25
-0x0094,17,dropitem,6:15
-0x009b,14,getcharnamerequest,10
-0x009f,-1,globalmessage,2:4
-0x00a2,14,solvecharname,10
-0x00a7,25,useskilltopos,10:14:18:23
-0x00f3,10,changedir,4:9
-0x00f5,34,wanttoconnection,7:15:25:29:33
-0x00f7,2,closekafra,0
-0x0113,11,takeitem,7
-0x0116,11,ticksend,7
-0x0190,22,useskilltoid,9:15:18
-0x0193,17,movefromkafra,3:13
-
-//2004-09-20aSakexe
-packet_ver: 11
-0x0072,18,useitem,10:14
-0x007e,25,movetokafra,6:21
-0x0085,9,actionrequest,3:8
-0x0089,14,walktoxy,11
-0x008c,109,useskilltoposinfo,16:20:23:27:29
-0x0094,19,dropitem,12:17
-0x009b,10,getcharnamerequest,6
-0x00a2,10,solvecharname,6
-0x00a7,29,useskilltopos,6:20:23:27
-0x00f3,18,changedir,8:17
-0x00f5,32,wanttoconnection,10:17:23:27:31
-0x0113,14,takeitem,10
-0x0116,14,ticksend,10
-0x0190,14,useskilltoid,4:7:10
-0x0193,12,movefromkafra,4:8
-
-//2004-10-05aSakexe
-packet_ver: 12
-0x0072,17,useitem,6:13
-0x007e,16,movetokafra,5:12
-0x0089,6,walktoxy,3
-0x008c,103,useskilltoposinfo,2:6:17:21:23
-0x0094,14,dropitem,5:12
-0x009b,15,getcharnamerequest,11
-0x00a2,12,solvecharname,8
-0x00a7,23,useskilltopos,3:6:17:21
-0x00f3,13,changedir,5:12
-0x00f5,33,wanttoconnection,12:18:24:28:32
-0x0113,10,takeitem,6
-0x0116,10,ticksend,6
-0x0190,20,useskilltoid,7:12:16
-0x0193,26,movefromkafra,10:22
-
-//2004-10-25aSakexe
-packet_ver: 13
-0x0072,13,useitem,5:9
-0x007e,13,movetokafra,6:9
-0x0085,15,actionrequest,4:14
-0x008c,108,useskilltoposinfo,6:9:23:26:28
-0x0094,12,dropitem,6:10
-0x009b,10,getcharnamerequest,6
-0x00a2,16,solvecharname,12
-0x00a7,28,useskilltopos,6:9:23:26
-0x00f3,15,changedir,6:14
-0x00f5,29,wanttoconnection,5:14:20:24:28
-0x0113,9,takeitem,5
-0x0116,9,ticksend,5
-0x0190,26,useskilltoid,4:10:22
-0x0193,22,movefromkafra,12:18
-
-//2004-11-01aSakexe
-0x0084,-1
-0x0215,6
-
-//2004-11-08aSakexe
-0x0084,2
-0x0216,6
-0x0217,2,blacksmith,0
-0x0218,2,alchemist,0
-0x0219,282
-0x021a,282
-0x021b,10
-0x021c,10
-
-//2004-11-15aSakexe
-0x021d,6,lesseffect,2
-
-//2004-11-29aSakexe
-packet_ver: 14
-0x0072,22,useskilltoid,8:12:18
-0x007e,30,useskilltopos,4:9:22:28
-0x0085,-1,globalmessage,2:4
-0x0089,7,ticksend,3
-0x008c,13,getcharnamerequest,9
-0x0094,14,movetokafra,4:10
-0x009b,2,closekafra,0
-0x009f,18,actionrequest,6:17
-0x00a2,7,takeitem,3
-0x00a7,7,walktoxy,4
-0x00f3,8,changedir,3:7
-0x00f5,29,wanttoconnection,3:10:20:24:28
-0x00f7,14,solvecharname,10
-0x0113,110,useskilltoposinfo,4:9:22:28:30
-0x0116,12,dropitem,4:10
-0x0190,15,useitem,3:11
-0x0193,21,movefromkafra,4:17
-0x0221,-1
-0x0222,6,weaponrefine,2
-0x0223,8
-
-//2004-12-13aSakexe
-//skipped: many packets being set to -1
-0x0066,3
-0x0070,3
-0x01ca,3
-0x021e,6
-0x021f,66
-0x0220,10
-
-//2005-01-10bSakexe
-packet_ver: 15
-0x0072,26,useskilltoid,8:16:22
-0x007e,114,useskilltoposinfo,10:18:22:32:34
-0x0085,23,changedir,12:22
-0x0089,9,ticksend,5
-0x008c,8,getcharnamerequest,4
-0x0094,20,movetokafra,10:16
-0x009b,32,wanttoconnection,3:12:23:27:31
-0x009f,17,useitem,5:13
-0x00a2,11,solvecharname,7
-0x00a7,13,walktoxy,10
-0x00f3,-1,globalmessage,2:4
-0x00f5,9,takeitem,5
-0x00f7,21,movefromkafra,11:17
-0x0113,34,useskilltopos,10:18:22:32
-0x0116,20,dropitem,15:18
-0x0190,20,actionrequest,9:19
-0x0193,2,closekafra,0
-
-//2005-03-28aSakexe
-0x0224,10
-0x0225,2,taekwon,0
-0x0226,282
-
-//2005-04-04aSakexe
-0x0227,18
-0x0228,18
-
-//2005-04-11aSakexe
-0x0229,15
-0x022a,58
-0x022b,57
-0x022c,64
-
-//2005-04-25aSakexe
-0x022d,5,hommenu,2:4
-0x0232,9,hommoveto,2:6
-0x0233,11,homattack,2:6:10
-0x0234,6,hommovetomaster,2
-
-//2005-05-09aSakexe
-packet_ver: 16
-0x0072,25,useskilltoid,6:10:21
-0x007e,102,useskilltoposinfo,5:9:12:20:22
-0x0085,11,changedir,7:10
-0x0089,8,ticksend,4
-0x008c,11,getcharnamerequest,7
-0x0094,14,movetokafra,7:10
-0x009b,26,wanttoconnection,4:9:17:21:25
-0x009f,14,useitem,4:10
-0x00a2,15,solvecharname,11
-0x00a7,8,walktoxy,5
-0x00f5,8,takeitem,4
-0x00f7,22,movefromkafra,14:18
-0x0113,22,useskilltopos,5:9:12:20
-0x0116,10,dropitem,5:8
-0x0190,19,actionrequest,5:18
-
-//2005-05-23aSakexe
-0x022e,69
-0x0230,12
-
-//2005-05-30aSakexe
-0x022e,71
-0x0235,-1
-0x0236,10
-0x0237,2,rankingpk,0
-0x0238,282
-
-//2005-05-31aSakexe
-0x0216,2
-0x0239,11
-
-//2005-06-08aSakexe
-0x0216,6
-0x0217,2,blacksmith,0
-0x022f,5
-0x0231,26,changehomunculusname,2
-0x023a,4
-0x023b,36,storagepassword,2:4:20
-0x023c,6
-
-//2005-06-22aSakexe
-0x022e,71
-
-//2005-06-28aSakexe
-packet_ver: 17
-0x0072,34,useskilltoid,6:17:30
-0x007e,113,useskilltoposinfo,12:15:18:31:33
-0x0085,17,changedir,8:16
-0x0089,13,ticksend,9
-0x008c,8,getcharnamerequest,4
-0x0094,31,movetokafra,16:27
-0x009b,32,wanttoconnection,9:15:23:27:31
-0x009f,19,useitem,9:15
-0x00a2,9,solvecharname,5
-0x00a7,11,walktoxy,8
-0x00f5,13,takeitem,9
-0x00f7,18,movefromkafra,11:14
-0x0113,33,useskilltopos,12:15:18:31
-0x0116,12,dropitem,3:10
-0x0190,24,actionrequest,11:23
-0x0216,-1
-0x023d,-1
-0x023e,4
-
-//2005-07-18aSakexe
-packet_ver: 18
-0x0072,19,useskilltoid,5:11:15
-0x007e,110,useskilltoposinfo,9:15:23:28:30
-0x0085,11,changedir,6:10
-0x0089,7,ticksend,3
-0x008c,11,getcharnamerequest,7
-0x0094,21,movetokafra,12:17
-0x009b,31,wanttoconnection,3:13:22:26:30
-0x009f,12,useitem,3:8
-0x00a2,18,solvecharname,14
-0x00a7,15,walktoxy,12
-0x00f5,7,takeitem,3
-0x00f7,13,movefromkafra,5:9
-0x0113,30,useskilltopos,9:15:23:28
-0x0116,12,dropitem,6:10
-0x0190,21,actionrequest,5:20
-0x0216,6
-0x023f,2,mailrefresh,0
-0x0240,8
-0x0241,6,mailread,2
-0x0242,-1
-0x0243,6,maildelete,2
-0x0244,6,mailgetattach,2
-0x0245,7
-0x0246,4,mailwinopen,2
-0x0247,8,mailsetattach,2:4
-0x0248,68
-0x0249,3
-0x024a,70
-0x024b,4,auctioncancelreg,2
-0x024c,8,auctionsetitem,2:4
-0x024d,14
-0x024e,6,auctioncancel,2
-0x024f,10,auctionbid,2:6
-0x0250,3
-0x0251,2
-0x0252,-1
-
-//2005-07-19bSakexe
-packet_ver: 19
-0x0072,34,useskilltoid,6:17:30
-0x007e,113,useskilltoposinfo,12:15:18:31:33
-0x0085,17,changedir,8:16
-0x0089,13,ticksend,9
-0x008c,8,getcharnamerequest,4
-0x0094,31,movetokafra,16:27
-0x009b,32,wanttoconnection,9:15:23:27:31
-0x009f,19,useitem,9:15
-0x00a2,9,solvecharname,5
-0x00a7,11,walktoxy,8
-0x00f5,13,takeitem,9
-0x00f7,18,movefromkafra,11:14
-0x0113,33,useskilltopos,12:15:18:31
-0x0116,12,dropitem,3:10
-0x0190,24,actionrequest,11:23
-
-//2005-08-01aSakexe
-0x0245,3
-0x0251,4
-
-//2005-08-08aSakexe
-0x024d,12,auctionregister,2:6:10
-0x024e,4
-
-//2005-08-17aSakexe
-0x0253,3
-0x0254,3,feelsaveok,2
-
-//2005-08-29aSakexe
-0x0240,-1
-0x0248,-1,mailsend,2:4:28:68:69
-0x0255,5
-0x0256,-1
-0x0257,8
-
-//2005-09-12bSakexe
-0x0256,5
-0x0258,2
-0x0259,3
-
-//2005-10-10aSakexe
-0x020e,32
-0x025a,-1
-0x025b,6,cooking,2:4
-
-//2005-10-13aSakexe
-0x007a,6
-0x0251,32
-0x025c,4,auctionbuysell,2
-
-//2005-10-17aSakexe
-0x007a,58
-0x025d,6,auctionclose,2
-0x025e,4
-
-//2005-10-24aSakexe
-0x025f,6
-0x0260,6
-
-//2005-11-07aSakexe
-0x024e,6,auctioncancel,2
-0x0251,34,auctionsearch,2:4:8:32
-
-//2006-01-09aSakexe
-0x0261,11
-0x0262,11
-0x0263,11
-0x0264,20
-0x0265,20
-0x0266,30
-0x0267,4
-0x0268,4
-0x0269,4
-0x026a,4
-0x026b,4
-0x026c,4
-0x026d,4
-0x026f,2
-0x0270,2
-0x0271,38
-0x0272,44
-
-//2006-01-26aSakexe
-0x0271,40
-
-//2006-03-06aSakexe
-0x0273,6
-0x0274,8
-
-//2006-03-13aSakexe
-0x0273,30,mailreturn,2:6
-
-//2006-03-27aSakexe
-packet_ver: 20
-0x0072,26,useskilltoid,11:18:22
-0x007e,120,useskilltoposinfo,5:15:29:38:40
-0x0085,12,changedir,7:11
-//0x0089,13,ticksend,9
-0x008c,12,getcharnamerequest,8
-0x0094,23,movetokafra,5:19
-0x009b,37,wanttoconnection,9:21:28:32:36
-0x009f,24,useitem,9:20
-0x00a2,11,solvecharname,7
-0x00a7,15,walktoxy,12
-0x00f5,13,takeitem,9
-0x00f7,26,movefromkafra,11:22
-0x0113,40,useskilltopos,5:15:29:38
-0x0116,17,dropitem,8:15
-0x0190,18,actionrequest,7:17
-
-//2006-10-23aSakexe
-0x006d,110
-
-//2006-04-24aSakexe to 2007-01-02aSakexe
-0x023e,8
-0x0277,84
-0x0278,2
-0x0279,2
-0x027a,-1
-0x027b,14
-0x027c,60
-0x027d,62
-0x027e,-1
-0x027f,8
-0x0280,12
-0x0281,4
-0x0282,284
-0x0283,6
-0x0284,14
-0x0285,6
-0x0286,4
-0x0287,-1
-0x0288,6
-0x0289,8
-0x028a,18
-0x028b,-1
-0x028c,46
-0x028d,34
-0x028e,4
-0x028f,6
-0x0290,4
-0x0291,4
-0x0292,2,autorevive,0
-0x0293,70
-0x0294,10
-0x0295,-1
-0x0296,-1
-0x0297,-1
-0x0298,8
-0x0299,6
-0x029a,27
-0x029c,66
-0x029d,-1
-0x029e,11
-0x029f,3,mermenu,2
-0x02a0,-1
-0x02a1,-1
-0x02a2,8
-
-//2007-01-08aSakexe
-packet_ver: 21
-0x0072,30,useskilltoid,10:14:26
-0x007e,120,useskilltoposinfo,10:19:23:38:40
-0x0085,14,changedir,10:13
-0x0089,11,ticksend,7
-0x008c,17,getcharnamerequest,13
-0x0094,17,movetokafra,4:13
-0x009b,35,wanttoconnection,7:21:26:30:34
-0x009f,21,useitem,7:17
-0x00a2,10,solvecharname,6
-0x00a7,8,walktoxy,5
-0x00f5,11,takeitem,7
-0x00f7,15,movefromkafra,3:11
-0x0113,40,useskilltopos,10:19:23:38
-0x0116,19,dropitem,11:17
-0x0190,10,actionrequest,4:9
-
-//2007-01-22aSakexe
-0x02a3,18
-0x02a4,2
-
-//2007-01-29aSakexe
-0x029b,72
-0x02a3,-1
-0x02a4,-1
-0x02a5,8
-
-// 2007-02-05aSakexe
-0x02aa,4
-0x02ab,36
-0x02ac,6
-
-//2007-02-12aSakexe
-packet_ver: 22
-0x0072,25,useskilltoid,6:10:21
-0x007e,102,useskilltoposinfo,5:9:12:20:22
-0x0085,11,changedir,7:10
-0x0089,8,ticksend,4
-0x008c,11,getcharnamerequest,7
-0x0094,14,movetokafra,7:10
-0x009b,26,wanttoconnection,4:9:17:21:25
-0x009f,14,useitem,4:10
-0x00a2,15,solvecharname,11
-//0x00a7,8,walktoxy,5
-0x00f5,8,takeitem,4
-0x00f7,22,movefromkafra,14:18
-0x0113,22,useskilltopos,5:9:12:20
-0x0116,10,dropitem,5:8
-0x0190,19,actionrequest,5:18
-
-//2007-05-07aSakexe
-0x01fd,15,repairitem,2:4:6:7:9:11:13
-
-//2007-02-27aSakexe to 2007-10-02aSakexe
-0x0288,10,cashshopbuy,2:4:6
-0x0289,12
-0x02a6,22
-0x02a7,22
-0x02a8,162
-0x02a9,58
-0x02ad,8
-0x02b0,85
-0x02b1,-1
-0x02b2,-1
-0x02b3,107
-0x02b4,6
-0x02b5,-1
-0x02b6,7,queststate,2:6
-0x02b7,7
-0x02b8,22
-0x02b9,191
-0x02ba,11,hotkey,2:4:5:9
-0x02bb,8
-0x02bc,6
-0x02bf,10
-0x02c0,2
-0x02c1,-1
-0x02c2,-1
-0x02c4,26,partyinvite2,2
-0x02c5,30
-0x02c6,30
-0x02c7,7,replypartyinvite2,2:6
-0x02c8,3,partytick,2
-0x02c9,3
-0x02ca,3
-0x02cb,20
-0x02cc,4
-0x02cd,26
-0x02ce,10
-0x02cf,6
-0x02d0,-1
-0x02d1,-1
-0x02d2,-1
-0x02d3,4,ZC_NOTIFY_BIND_ON_EQUIP,2
-0x02d4,29
-0x02d5,2
-0x02d6,6,viewplayerequip,2
-0x02d7,-1
-0x02d8,10,equiptickbox,2:6
-0x02d9,10
-0x02da,3
-0x02db,-1,battlechat,2:4
-0x02dc,-1
-0x02dd,32
-0x02de,6
-0x02df,36
-0x02e0,34
-
-//2007-10-23aSakexe
-0x02cb,65
-0x02cd,71
-
-//2007-11-06aSakexe
-0x0078,55
-0x007c,42
-0x022c,65
-0x029b,80
-
-//2007-11-13aSakexe
-0x02e1,33
-
-//2007-11-20aSakexe
-//0x01df,10 <- ???
-0x02e2,14
-0x02e3,25
-0x02e4,8
-0x02e5,8
-0x02e6,6
-
-//2007-11-27aSakexe
-0x02e7,-1
-
-//2008-01-02aSakexe
-0x01df,6,gmreqaccname,2
-0x02e8,-1
-0x02e9,-1
-0x02ea,-1
-0x02eb,13
-0x02ec,67
-0x02ed,59
-0x02ee,60
-0x02ef,8
-
-//2008-03-18aSakexe
-0x02bf,-1
-0x02c0,-1
-0x02f0,10
-0x02f1,2,progressbar,0
-0x02f2,2
-
-//2008-03-25bSakexe
-0x02f3,-1
-0x02f4,-1
-0x02f5,-1
-0x02f6,-1
-0x02f7,-1
-0x02f8,-1
-0x02f9,-1
-0x02fa,-1
-0x02fb,-1
-0x02fc,-1
-0x02fd,-1
-0x02fe,-1
-0x02ff,-1
-0x0300,-1
-
-//2008-04-01aSakexe
-0x0301,-1
-0x0302,-1
-0x0303,-1
-0x0304,-1
-0x0305,-1
-0x0306,-1
-0x0307,-1
-0x0308,-1
-0x0309,-1
-0x030a,-1
-0x030b,-1
-0x030c,-1
-0x030d,-1
-0x030e,-1
-0x030f,-1
-0x0310,-1
-0x0311,-1
-0x0312,-1
-0x0313,-1
-0x0314,-1
-0x0315,-1
-0x0316,-1
-0x0317,-1
-0x0318,-1
-0x0319,-1
-0x031a,-1
-0x031b,-1
-0x031c,-1
-0x031d,-1
-0x031e,-1
-0x031f,-1
-0x0320,-1
-0x0321,-1
-0x0322,-1
-0x0323,-1
-0x0324,-1
-0x0325,-1
-0x0326,-1
-0x0327,-1
-0x0328,-1
-0x0329,-1
-0x032a,-1
-0x032b,-1
-0x032c,-1
-0x032d,-1
-0x032e,-1
-0x032f,-1
-0x0330,-1
-0x0331,-1
-0x0332,-1
-0x0333,-1
-0x0334,-1
-0x0335,-1
-0x0336,-1
-0x0337,-1
-0x0338,-1
-0x0339,-1
-0x033a,-1
-0x033b,-1
-0x033c,-1
-0x033d,-1
-0x033e,-1
-0x033f,-1
-0x0340,-1
-0x0341,-1
-0x0342,-1
-0x0343,-1
-0x0344,-1
-0x0345,-1
-0x0346,-1
-0x0347,-1
-0x0348,-1
-0x0349,-1
-0x034a,-1
-0x034b,-1
-0x034c,-1
-0x034d,-1
-0x034e,-1
-0x034f,-1
-0x0350,-1
-0x0351,-1
-0x0352,-1
-0x0353,-1
-0x0354,-1
-0x0355,-1
-0x0356,-1
-0x0357,-1
-0x0358,-1
-0x0359,-1
-0x035a,-1
-
-//2008-05-27aSakexe
-0x035b,-1
-0x035c,2
-0x035d,-1
-0x035e,2
-0x035f,-1
-0x0389,-1
-
-//2008-08-20aSakexe
-0x040c,-1
-0x040d,-1
-0x040e,-1
-0x040f,-1
-0x0410,-1
-0x0411,-1
-0x0412,-1
-0x0413,-1
-0x0414,-1
-0x0415,-1
-0x0416,-1
-0x0417,-1
-0x0418,-1
-0x0419,-1
-0x041a,-1
-0x041b,-1
-0x041c,-1
-0x041d,-1
-0x041e,-1
-0x041f,-1
-0x0420,-1
-0x0421,-1
-0x0422,-1
-0x0423,-1
-0x0424,-1
-0x0425,-1
-0x0426,-1
-0x0427,-1
-0x0428,-1
-0x0429,-1
-0x042a,-1
-0x042b,-1
-0x042c,-1
-0x042d,-1
-0x042e,-1
-0x042f,-1
-0x0430,-1
-0x0431,-1
-0x0432,-1
-0x0433,-1
-0x0434,-1
-0x0435,-1
-
-//2008-09-10aSakexe
-packet_ver: 23
-0x0436,19,wanttoconnection,2:6:10:14:18
-0x0437,7,actionrequest,2:6
-0x0438,10,useskilltoid,2:4:6
-0x0439,8,useitem,2:4
-
-//2008-11-13aSakexe
-0x043d,8
-0x043e,-1
-0x043f,8
-
-//2008-11-26aSakexe
-0x01a2,37
-0x0440,10
-0x0441,4
-
-//2008-12-10aSakexe
-0x0442,-1
-0x0443,8,skillselectmenu,2:6
-
-//2009-01-14aSakexe
-0x043f,25
-0x0444,-1
-0x0445,10
-
-//2009-02-18aSakexe
-0x0446,14
-
-//2009-02-25aSakexe
-0x0448,-1
-
-//2009-03-30aSakexe
-0x0449,4
-
-//2009-04-08aSakexe
-0x02a6,-1
-0x02a7,-1
-0x044a,6,clientversion,2
-
-//Renewal Clients
-//2008-08-27aRagexeRE
-packet_ver: 24
-0x0072,22,useskilltoid,9:15:18
-0x007c,44
-0x007e,105,useskilltoposinfo,10:14:18:23:25
-0x0085,10,changedir,4:9
-0x0089,11,ticksend,7
-0x008c,14,getcharnamerequest,10
-0x0094,19,movetokafra,3:15
-0x009b,34,wanttoconnection,7:15:25:29:33
-0x009f,20,useitem,7:20
-0x00a2,14,solvecharname,10
-0x00a7,9,walktoxy,6
-0x00f5,11,takeitem,7
-0x00f7,17,movefromkafra,3:13
-0x0113,25,useskilltopos,10:14:18:23
-0x0116,17,dropitem,6:15
-0x0190,23,actionrequest,9:22
-0x02e2,20
-0x02e3,22
-0x02e4,11
-0x02e5,9
-
-//2008-09-10aRagexeRE
-packet_ver: 25
-0x0436,19,wanttoconnection,2:6:10:14:18
-0x0437,7,actionrequest,2:6
-0x0438,10,useskilltoid,2:4:6
-0x0439,8,useitem,2:4
-
-//2008-11-12aRagexeRE
-0x043d,8
-//0x043e,-1
-0x043f,8
-
-//2008-12-17aRagexeRE
-0x01a2,37
-//0x0440,10
-//0x0441,4
-//0x0442,8
-//0x0443,8
-
-//2008-12-17bRagexeRE
-0x006d,114
-
-//2009-01-21aRagexeRE
-0x043f,25
-//0x0444,-1
-//0x0445,10
-
-//2009-02-18aRagexeRE
-//0x0446,14
-
-//2009-02-26cRagexeRE
-//0x0448,-1
-
-//2009-04-01aRagexeRE
-//0x0449,4
-
-//2009-05-14aRagexeRE
-//0x044b,2
-
-//2009-05-20aRagexeRE
-//0x07d0,6
-//0x07d1,2
-//0x07d2,-1
-//0x07d3,4
-//0x07d4,4
-//0x07d5,4
-//0x07d6,4
-//0x0447,2
-
-//2009-06-03aRagexeRE
-0x07d7,8,partychangeoption,2:6:7
-0x07d8,8
-0x07d9,254
-0x07da,6,partychangeleader,2
-
-//2009-06-10aRagexeRE
-//0x07db,8
-
-//2009-06-17aRagexeRE
-0x07d9,268
-//0x07dc,6
-//0x07dd,54
-//0x07de,30
-//0x07df,54
-
-//2009-07-01aRagexeRE
-//0x0275,37
-//0x0276,-1
-
-//2009-07-08aRagexeRE
-//0x07e0,58
-
-//2009-07-15aRagexeRE
-0x07e1,15
-
-//2009-08-05aRagexeRE
-0x07e2,8
-
-//2009-08-18aRagexeRE
-0x07e3,6
-0x07e4,-1,itemlistwindowselected,2:4:8:12
-0x07e6,8
-
-//2009-08-25aRagexeRE
-//0x07e6,28
-0x07e7,5
-
-//2009-09-22aRagexeRE
-0x07e5,8
-0x07e6,8
-0x07e7,32
-0x07e8,-1
-0x07e9,5
-
-//2009-09-29aRagexeRE
-//0x07ea,2
-//0x07eb,-1
-//0x07ec,6
-//0x07ed,8
-//0x07ee,6
-//0x07ef,8
-//0x07f0,4
-//0x07f2,4
-//0x07f3,3
-
-//2009-10-06aRagexeRE
-//0x07ec,8
-//0x07ed,10
-//0x07f0,8
-//0x07f1,15
-//0x07f2,6
-//0x07f3,4
-//0x07f4,3
-
-//2009-10-27aRagexeRE
-0x07f5,6,gmfullstrip,2
-0x07f6,14
-
-//2009-11-03aRagexeRE
-0x07f7,-1
-0x07f8,-1
-0x07f9,-1
-
-//2009-11-17aRagexeRE
-0x07fa,8
-
-//2009-11-24aRagexeRE
-0x07fb,25
-
-//2009-12-01aRagexeRE
-0x07fc,10
-0x07fd,-1,ZC_BROADCASTING_SPECIAL_ITEM_OBTAIN,0
-0x07fe,26
-//0x07ff,-1
-
-//2009-12-15aRagexeRE
-0x0800,-1
-//0x0801,-1
-
-//2009-12-22aRagexeRE
-0x0802,18,bookingregreq,2:4:6		// Booking System
-0x0803,4
-0x0804,8		// Booking System
-0x0805,-1
-0x0806,4,bookingdelreq,2		// Booking System
-//0x0807,2
-0x0808,4		// Booking System
-//0x0809,14
-//0x080A,50
-//0x080B,18
-//0x080C,6
-
-//2009-12-29aRagexeRE
-0x0804,14,bookingsearchreq,2:4:6:8:12		// Booking System
-0x0806,2,bookingdelreq,0		// Booking System
-0x0807,4
-0x0808,14,bookingupdatereq,2		// Booking System
-0x0809,50
-0x080A,18
-0x080B,6		// Booking System
-
-//2010-01-05aRagexeRE
-0x0801,-1,purchasereq2,2:4:8:12
-
-//2010-01-26aRagexeRE
-//0x080C,2
-//0x080D,3
-0x080E,14
-
-//2010-02-09aRagexeRE
-//0x07F0,6
-
-//2010-02-23aRagexeRE
-0x080F,20
-
-//2010-03-03aRagexeRE
-0x0810,3
-0x0811,-1,reqopenbuyingstore,2:4:8:9:89
-//0x0812,86
-//0x0813,6
-//0x0814,6
-//0x0815,-1
-//0x0817,-1
-//0x0818,6
-//0x0819,4
-
-//2010-03-09aRagexeRE
-0x0813,-1
-//0x0814,2
-//0x0815,6
-0x0816,6
-0x0818,-1
-//0x0819,10
-//0x081A,4
-//0x081B,4
-//0x081C,6
-0x081d,22
-0x081e,8
-
-//2010-03-23aRagexeRE
-//0x081F,-1
-
-//2010-04-06aRagexeRE
-//0x081A,6
-
-//2010-04-13aRagexeRE
-//0x081A,10
-0x0820,11
-//0x0821,2
-//0x0822,9
-//0x0823,-1
-
-//2010-04-14dRagexeRE
-//0x081B,8
-
-//2010-04-20aRagexeRE
-0x0812,8
-0x0814,86
-0x0815,2,reqclosebuyingstore,0
-0x0817,6,reqclickbuyingstore,2
-0x0819,-1,reqtradebuyingstore,2:4:8:12
-0x081a,4
-0x081b,10
-0x081c,10
-0x0824,6
-
-//2010-06-01aRagexeRE
-//0x0825,-1
-//0x0826,4
-0x0835,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0836,-1
-0x0837,3
-//0x0838,3
-
-//2010-06-08aRagexeRE
-0x0838,2,searchstoreinfonextpage,0
-0x083A,4 	// Search Stalls Feature
-0x083B,2,closesearchstoreinfo,0
-0x083C,12,searchstoreinfolistitemclick,2:6:10
-0x083D,6
-
-//2010-06-15aRagexeRE
-//0x083E,26
-
-//2010-06-22aRagexeRE
-//0x083F,22
-
-//2010-06-29aRagexeRE
-0x00AA,9,ZC_WEAR_EQUIP_ACK,2:4:6:8
-//0x07F1,18
-//0x07F2,8
-//0x07F3,6
-
-//2010-07-01aRagexeRE
-0x083A,5 	// Search Stalls Feature
-
-//2010-07-13aRagexeRE
-//0x0827,6
-//0x0828,14
-//0x0829,6
-//0x082A,10
-//0x082B,6
-//0x082C,14
-//0x0840,-1
-//0x0841,19
-
-//2010-07-14aRagexeRE
-//0x0841,4
-
-//2010-08-03aRagexeRE
-0x0839,66
-0x0842,6,recall2,2
-0x0843,6,remove2,2
-
-//2010-11-24aRagexeRE
-packet_ver: 26
-0x0288,-1,cashshopbuy,2:4:8:10
-0x0436,19,wanttoconnection,2:6:10:14:18
-0x035f,5,walktoxy,2
-0x0360,6,ticksend,2
-0x0361,5,changedir,2:4
-0x0362,6,takeitem,2
-0x0363,6,dropitem,2:4
-0x0364,8,movetokafra,2:4
-0x0365,8,movefromkafra,2:4
-0x0366,10,useskilltopos,2:4:6:8
-0x0367,90,useskilltoposinfo,2:4:6:8:10
-0x0368,6,getcharnamerequest,2
-0x0369,6,solvecharname,2
-0x0856,-1
-0x0857,-1
-0x0858,-1
-0x0859,-1
-0x08d0,9,ZC_WEAR_EQUIP_ACK,2:4:6:8
-
-//2011-10-05aRagexeRE
-packet_ver: 27
-packet_keys: 0x291E6762,0x77CD391A,0x60AC2F16 // [Shakto]
-0x0364,5,walktoxy,2
-0x0817,6,ticksend,2
-0x0366,5,changedir,2:4
-0x0815,6,takeitem,2
-0x0885,6,dropitem,2:4
-0x0893,8,movetokafra,2:4
-0x0897,8,movefromkafra,2:4
-0x0369,10,useskilltopos,2:4:6:8
-0x08ad,90,useskilltoposinfo,2:4:6:8:10
-0x088a,6,getcharnamerequest,2
-0x0838,6,solvecharname,2
-0x0439,8,useitem,2:4
-0x08d2,10
-0x08d1,7
-0x0846,4,cashshopreqtab,2 //2011-07-18
-
-// 2011-11-02aRagexe
-packet_ver: 28
-packet_keys: 0x5324329D,0x5D545D52,0x06137269 // [Shakto]
-0x0436,26,friendslistadd,2
-0x0898,5,hommenu,2:4
-0x0281,36,storagepassword,2:4:20
-0x088d,26,partyinvite2,2
-0x083c,19,wanttoconnection,2:6:10:14:18
-0x08aa,7,actionrequest,2:6
-0x02c4,10,useskilltoid,2:4:6
-0x0811,-1,itemlistwindowselected,2:4:8:12
-0x0890,8
-0x08a5,18,bookingregreq,2:4:6
-0x0835,-1,reqopenbuyingstore,2:4:8:9:89
-0x089b,2,reqclosebuyingstore,0
-0x08a1,6,reqclickbuyingstore,2
-0x089e,-1,reqtradebuyingstore,2:4:8:12
-0x08ab,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x088b,2,searchstoreinfonextpage,0
-0x08a2,12,searchstoreinfolistitemclick,2:6:10
-0x08cf,10 //Amulet spirits
-
-//2012-03-07fRagexeRE
-packet_ver:29
-packet_keys: 0x382A6DEF,0x5CBE7202,0x61F46637 // [Shakto]
-0x086A,19,wanttoconnection,2:6:10:14:18
-0x0437,5,walktoxy,2
-0x0887,6,ticksend,2
-0x0890,5,changedir,2:4
-0x0865,6,takeitem,2
-0x02C4,6,dropitem,2:4
-0x093B,8,movetokafra,2:4
-0x0963,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x096A,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x0369,26,friendslistadd,2
-0x0863,5,hommenu,2:4
-0x0861,36,storagepassword,2:4:20
-0x0929,26,partyinvite2,2
-0x0885,7,actionrequest,2:6
-0x0889,10,useskilltoid,2:4:6
-0x0870,-1,itemlistwindowselected,2:4:8:12
-//0x0926,41,bookingregreq,2:4:6
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x0817,2,reqclosebuyingstore,0
-0x0360,6,reqclickbuyingstore,2
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0884,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0835,2,searchstoreinfonextpage,0
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0439,8,useitem,2:4
-0x0365,41,bookingregreq,2:4:6
-
-// New Packet
-0x090F,-1		// ZC_NOTIFY_NEWENTRY7
-0x0914,-1		// ZC_NOTIFY_MOVEENTRY8
-0x0915,-1		// ZC_NOTIFY_STANDENTRY9
-
-//2012-04-10aRagexeRE
-packet_ver: 30
-packet_keys: 0x01581359,0x452D6FFA,0x6AFB6E2E // [Shakto]
-0x01fd,15,repairitem,2:4:6:7:9:11:13
-0x089c,26,friendslistadd,2
-0x0885,5,hommenu,2:4
-0x0961,36,storagepassword,2:4:20
-0x0288,-1,cashshopbuy,2:4:8:10
-0x091c,26,partyinvite2,2
-0x094b,19,wanttoconnection,2:6:10:14:18
-0x0369,7,actionrequest,2:6
-0x083c,10,useskilltoid,2:4:6
-0x0439,8,useitem,2:4
-0x0945,-1,itemlistwindowselected,2:4:8:12
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x0817,2,reqclosebuyingstore,0
-0x0360,6,reqclickbuyingstore,2
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0835,2,searchstoreinfonextpage,0
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0437,5,walktoxy,2
-0x0886,6,ticksend,2
-0x0871,5,changedir,2:4
-0x0938,6,takeitem,2
-0x0891,6,dropitem,2:4
-0x086c,8,movetokafra,2:4
-0x08a6,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x0889,6,getcharnamerequest,2
-0x0884,6,solvecharname,2
-0x08e6,4
-0x08e7,10,bookingsearchreq,2:4:6:8:12
-0x08e8,-1
-0x08e9,2,bookingdelreq,0
-0x08ea,4
-0x08eb,39,bookingupdatereq,2
-0x08ec,73
-0x08ed,43
-0x08ee,6
-0x08ef,6,bookingignorereq,2
-0x08f0,6
-0x08f1,6,bookingjoinpartyreq,2
-0x08f2,36
-0x08f3,-1
-0x08f4,6
-0x08f5,-1,bookingsummonmember,2:4
-0x08f6,22
-0x08f7,3
-0x08f8,7
-0x08f9,6
-0x08fa,6
-0x08fb,6,bookingcanceljoinparty,2
-0x0907,5,moveitem,2:4
-0x0908,5
-0x08d7,28,battlegroundreg,2:4
-0x0977,14 //Monster HP Bar
-0x0916,26,guildinvite2,2
-0x091d,41,bookingregreq,2:4:6
-0x08cb,10,ZC_PERSONAL_INFOMATION,2:4:6:8:10:11:13:15 //Still need further information
-// Merge Item
-0x096D,-1,ZC_MERGE_ITEM_OPEN,2:4 // ZC_MERGE_ITEM_OPEN
-0x096E,-1,mergeitem_req,2:4 // CZ_REQ_MERGE_ITEM
-0x096F,7,ZC_ACK_MERGE_ITEM,2:4:6 // ZC_ACK_MERGE_ITEM
-0x0974,2,mergeitem_cancel,0 // CZ_CANCEL_MERGE_ITEM
-0x0844,2,cashshopopen,0
-0x0849,16 //clif_cashshop_result
-0x0848,-1,cashshopbuy,2:6:4:10
-0x084a,2,cashshopclose,0
-0x08c9,2,cashshopitemlist,0
-
-//2012-04-18aRagexeRE [Special Thanks to Judas!]
-packet_ver: 31
-packet_keys: 0x01540E48,0x13041224,0x31247924 // [Shakto]
-0x023B,26,friendslistadd,2
-0x0361,5,hommenu,2:4
-0x08A8,36,storagepassword,2:4:20
-0x0802,26,partyinvite2,2
-0x022D,19,wanttoconnection,2:6:10:14:18
-0x0281,-1,itemlistwindowselected,2:4:8:12
-0x035F,6,ticksend,2
-0x0202,5,changedir,2:4
-0x07E4,6,takeitem,2
-0x0362,6,dropitem,2:4
-0x07EC,8,movetokafra,2:4
-0x0364,8,movefromkafra,2:4
-0x096A,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x08E5,41,bookingregreq,2:4:6    //Added to prevent disconnections
-0x08d2,10
-
-//2012-06-18
-packet_ver: 32
-packet_keys: 0x261F261F,0x261F261F,0x261F261F // [Shakto]
-0x0983,29 // ZC_MSG_STATE_CHANGE3
-0x0861,41,bookingregreq,2:4:6 //actually 12-05-03
-
-//2012-07-02aRagexeRE (unstable)
-packet_ver: 33
-packet_keys: 0x25733B31,0x53486CFD,0x398649BD // [Shakto]
-0x0363,19,wanttoconnection,2:6:10:14:18
-0x0364,6,ticksend,2
-0x085a,7,actionrequest,2:6
-0x0861,8,movefromkafra,2:4
-0x0862,10,useskilltoid,2:4:6
-0x0863,10,useskilltopos,2:4:6:8
-0x0886,6,solvecharname,2
-0x0889,90,useskilltoposinfo,2:4:6:8:10
-0x089e,6,dropitem,2:4
-0x089f,6,takeitem,2
-0x08a0,8,movetokafra,2:4
-0x094a,6,getcharnamerequest,2
-0x0953,5,walktoxy,2
-0x0960,5,changedir,2:4
-0x0879,41,bookingregreq,2:4:6
-
-//2013-03-20Ragexe (Judas)
-packet_ver: 34
-packet_keys: 0x3F094C49,0x55F86C1E,0x58AA359A // [Shakto]
-0x014f,6,guildrequestinfo,2
-0x01fd,15,repairitem,2:4:6:7:9:11:13
-//0x0281,-1,itemlistwindowselected,2:4:8:12
-0x035f,6,reqclickbuyingstore,2
-0x0363,6,ticksend,2
-0x0365,12,searchstoreinfolistitemclick,2:6:10
-0x0438,6,dropitem,2:4
-0x0447,2,booking_playcancel,0 // CZ_BLOCKING_PLAY_CANCEL
-0x044A,6,clientversion,2
-0x0844,2,cashshopopen,0
-0x0849,16 //clif_cashshop_result
-0x0848,-1,cashshopbuy,2:6:4:10
-0x084a,2,cashshopclose,0
-0x084b,19 //fallitem4
-0x085a,90,useskilltoposinfo,2:4:6:8:10
-0x085d,18,bookingregreq,2:4:6
-0x0868,-1,itemlistwindowselected,2:4:8:12
-0x086d,26,partyinvite2,2
-0x086f,26,friendslistadd,2
-0x0874,8,movefromkafra,2:4
-0x0881,5,walktoxy,2
-0x0886,2,reqclosebuyingstore,0
-0x0888,19,wanttoconnection,2:6:10:14:18
-0x088e,7,actionrequest,2:6
-0x0897,5,changedir,2:4
-0x0898,6,getcharnamerequest,2
-0x089b,10,useskilltoid,2:4:6
-0x08ac,8,movetokafra,2:4
-0x08c9,2,cashshopitemlist,0
-0x08cf,10 //Amulet spirits
-0x08d2,10
-0x0907,5,moveitem,2:4
-0x0908,5
-0x0922,-1,reqtradebuyingstore,2:4:8:12
-//0x092e,2,searchstoreinfonextpage,0
-0x0933,6,takeitem,2
-0x0938,-1,reqopenbuyingstore,2:4:8:9:89
-0x093f,5,hommenu,2:4
-0x0947,36,storagepassword,2:4:20
-0x094c,6,solvecharname,2
-0x094e,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0959,10,useskilltopos,2:4:6:8
-//0x095a,8,mailsetattach,2:4
-0x0977,14 //Monster HP Bar
-0x0978,6,reqworldinfo,2
-0x0979,50 //ackworldinfo
-0x097b,16,ZC_PERSONAL_INFOMATION,2:4:8:12:16:17:21:25 //Still need further information
-//0x0981,12,ZC_PERSONAL_INFOMATION_CHN,2:4:6:8:12:13:15:17:10 // Disabled until further information is found.
-0x0990,31 //additem
-0x0991,-1 //inv itemlist normal
-0x0992,-1 //inv itemlist equip
-0x0993,-1 //cart itemlist normal
-0x0994,-1 //cart itemlist equip
-0x0995,-1 //store itemlist normal
-0x0996,-1 //store itemlist equip
-0x0997,-1 //ZC_EQUIPWIN_MICROSCOPE_V5
-0x0998,8,equipitem,2:4 // CZ_REQ_WEAR_EQUIP_V5
-0x0999,11,ZC_WEAR_EQUIP_ACK,2:4:8:10 // cz_wear_equipv5
-0x099a,9 // take_off_equipv5
-0x099b,8 //maptypeproperty2
-
-// New Packets
-0x08C8,34	// ZC_NOTIFY_ACT3
-0x08ff,24 	// ZC_EFST_SET_ENTER
-0x0984,28 	// ZC_EFST_SET_ENTER2
-0x099f,22 	// ZC_SKILL_ENTRY4
-
-//2013-05-15aRagexe (Yommy)
-packet_ver: 35
-packet_keys: 0x75794A38,0x58A96BC1,0x296E6FB8 // [Shakto]
-0x0369,7,actionrequest,2:6
-0x083C,10,useskilltoid,2:4:6
-0x0437,5,walktoxy,2
-0x035F,6,ticksend,2
-0x0362,5,changedir,2:4
-0x08A1,6,takeitem,2
-0x0944,6,dropitem,2:4
-0x0887,8,movetokafra,2:4
-0x08AC,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x096A,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0835,2,searchstoreinfonextpage,0
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0360,6,reqclickbuyingstore,2
-0x0817,2,reqclosebuyingstore,0
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x092D,18,bookingregreq,2:4:6
-//0x08AA,8 CZ_JOIN_BATTLE_FIELD
-0x0963,-1,itemlistwindowselected,2:4:8:12
-0x0943,19,wanttoconnection,2:6:10:14:18
-0x0947,26,partyinvite2,2
-//0x0862,4 CZ_GANGSI_RANK
-0x0962,26,friendslistadd,2
-0x0931,5,hommenu,2:4
-0x093e,36,storagepassword,2:4:20
-
-//2013-05-22Ragexe (Yommy)
-packet_ver: 36
-packet_keys: 0x6948050B,0x06511D9D,0x725D4DF1 // [Shakto]
-0x08A2,7,actionrequest,2:6
-0x095C,10,useskilltoid,2:4:6
-0x0360,5,walktoxy,2
-0x07EC,6,ticksend,2
-0x0925,5,changedir,2:4
-0x095E,6,takeitem,2
-0x089C,6,dropitem,2:4
-0x08a3,8,movetokafra,2:4
-0x087E,8,movefromkafra,2:4
-0x0811,10,useskilltopos,2:4:6:8
-0x0964,90,useskilltoposinfo,2:4:6:8:10
-0x08a6,6,getcharnamerequest,2
-0x0369,6,solvecharname,2
-0x093e,12,searchstoreinfolistitemclick,2:6:10
-0x08aa,2,searchstoreinfonextpage,0
-0x095b,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0952,-1,reqtradebuyingstore,2:4:8:12
-0x0368,6,reqclickbuyingstore,2
-0x086E,2,reqclosebuyingstore,0
-0x0874,-1,reqopenbuyingstore,2:4:8:9:89
-0x089B,18,bookingregreq,2:4:6
-//0x0965,8 CZ_JOIN_BATTLE_FIELD
-0x086A,-1,itemlistwindowselected,2:4:8:12
-0x08A9,19,wanttoconnection,2:6:10:14:18
-0x0950,26,partyinvite2,2
-//0x08AC,4 CZ_GANGSI_RANK
-0x0362,26,friendslistadd,2
-0x0926,5,hommenu,2:4
-0x088e,36,storagepassword,2:4:20
-
-//2013-05-29Ragexe (Shakto)
-packet_ver: 37
-packet_keys: 0x023A6C87,0x14BF1F1E,0x5CC70CC9 // [Shakto]
-0x0890,7,actionrequest,2:6
-0x0438,10,useskilltoid,2:4:6
-0x0876,5,walktoxy,2
-0x0897,6,ticksend,2
-0x0951,5,changedir,2:4
-0x0895,6,takeitem,2
-0x08A7,6,dropitem,2:4
-0x0938,8,movetokafra,2:4
-0x0957,8,movefromkafra,2:4
-0x0917,10,useskilltopos,2:4:6:8
-0x085E,90,useskilltoposinfo,2:4:6:8:10
-0x0863,6,getcharnamerequest,2
-0x0937,6,solvecharname,2
-0x085A,12,searchstoreinfolistitemclick,2:6:10
-0x0941,2,searchstoreinfonextpage,0
-0x0918,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0936,-1,reqtradebuyingstore,2:4:8:12
-0x0892,6,reqclickbuyingstore,2
-0x0964,2,reqclosebuyingstore,0
-0x0869,-1,reqopenbuyingstore,2:4:8:9:89
-0x0874,18,bookingregreq,2,4:6
-//0x088E,8 // CZ_JOIN_BATTLE_FIELD
-0x0958,-1,itemlistwindowselected,2:4:8:12
-0x0919,19,wanttoconnection,2:6:10:14:18
-0x08A8,26,partyinvite2,2
-//0x0888,4 // CZ_GANGSI_RANK
-0x0877,26,friendslistadd,2
-0x023B,5,hommenu,2:4
-0x0956,36,storagepassword,2:4:20
-
-//2013-06-05Ragexe (Shakto)
-packet_ver: 38
-packet_keys: 0x646E08D9,0x5F153AB5,0x61B509B5 // [Shakto]
-0x0369,7,actionrequest,2:6
-0x083C,10,useskilltoid,2:4:6
-0x0437,5,walktoxy,2
-0x035F,6,ticksend,2
-0x0202,5,changedir,2:4
-0x07E4,6,takeitem,2
-0x0362,6,dropitem,2:4
-0x07EC,8,movetokafra,2:4
-0x0364,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x096A,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0835,2,searchstoreinfonextpage,0
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0360,6,reqclickbuyingstore,2
-0x0817,2,reqclosebuyingstore,0
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x0365,18,bookingregreq,2:4:6
-//0x0363,8 // CZ_JOIN_BATTLE_FIELD
-0x0281,-1,itemlistwindowselected,2:4:8:12
-0x022D,19,wanttoconnection,2:6:10:14:18
-0x0802,26,partyinvite2,2
-//0x0436,4 // CZ_GANGSI_RANK
-0x023B,26,friendslistadd,2
-0x0361,5,hommenu,2,4
-0x0883,36,storagepassword,2:4:20
-0x097C,4,ranklist,2
-
-//2013-06-12Ragexe (Shakto)
-packet_ver: 39
-packet_keys: 0x6D166F66,0x3C000FCF,0x295B0FCB // [Shakto]
-0x0369,7,actionrequest,2:6
-0x083C,10,useskilltoid,2:4:6
-0x0437,5,walktoxy,2
-0x035F,6,ticksend,2
-0x087E,5,changedir,2:4
-0x07E4,6,takeitem,2
-0x0362,6,dropitem,2:4
-0x07EC,8,movetokafra,2:4
-0x0364,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x096A,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0835,2,searchstoreinfonextpage,0
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0360,6,reqclickbuyingstore,2
-0x0817,2,reqclosebuyingstore,0
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x0365,18,bookingregreq,2:4:6
-//0x0363,8 // CZ_JOIN_BATTLE_FIELD
-0x0281,-1,itemlistwindowselected,2:4:8:12
-0x0919,19,wanttoconnection,2:6:10:14:18
-0x0802,26,partyinvite2,2
-//0x0436,4 // CZ_GANGSI_RANK
-0x0940,26,friendslistadd,2
-0x093A,5,hommenu,2:4
-0x0964,36,storagepassword,2:4:20
-
-//2013-06-18Ragexe (Shakto)
-packet_ver: 40
-packet_keys: 0x434115DE,0x34A10FE9,0x6791428E // [Shakto]
-0x0889,7,actionrequest,2:6
-0x0951,10,useskilltoid,2:4:6
-0x088E,5,walktoxy,2
-0x0930,6,ticksend,2
-0x08A6,5,changedir,2:4
-0x0962,6,takeitem,2
-0x0917,6,dropitem,2:4
-0x0885,8,movetokafra,2:4
-0x0936,8,movefromkafra,2:4
-0x096A,10,useskilltopos,2:4:6:8
-0x094F,90,useskilltoposinfo,2:4:6:8:10
-0x0944,6,getcharnamerequest,2
-0x0945,6,solvecharname,2
-0x0890,12,searchstoreinfolistitemclick,2:6:10
-0x0363,2,searchstoreinfonextpage,0
-0x0281,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0891,-1,reqtradebuyingstore,2:4:8:12
-0x0862,6,reqclickbuyingstore,2
-0x085A,2,reqclosebuyingstore,0
-0x0932,-1,reqopenbuyingstore,2:4:8:9:89
-0x08A7,18,bookingregreq,2:4:6
-//0x087A,8 // CZ_JOIN_BATTLE_FIELD
-0x0942,-1,itemlistwindowselected,2:4:8:12
-0x095B,19,wanttoconnection,2:6:10:14:18
-0x0887,26,partyinvite2,2
-//0x0878,4 // CZ_GANGSI_RANK
-0x0953,26,friendslistadd,2
-0x02C4,5,hommenu,2:4
-0x0864,36,storagepassword,2:4:20
-
-//2013-06-26Ragexe
-packet_ver: 41
-packet_keys: 0x38F453EF,0x6A040FD8,0X65BD6668 // [Shakto]
-0x0369,7,actionrequest,2:6
-0x083C,10,useskilltoid,2:4:6
-0x0437,5,walktoxy,2
-0x035F,6,ticksend,2
-0x094D,5,changedir,2:4
-0x088B,6,takeitem,2
-0x0952,6,dropitem,2:4
-0x0921,8,movetokafra,2:4
-0x0817,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x096A,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0835,2,searchstoreinfonextpage,0
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0360,6,reqclickbuyingstore,2
-0x0365,2,reqclosebuyingstore,0
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x0894,18,bookingregreq,2:4:6
-//0x0860,8 // CZ_JOIN_BATTLE_FIELD
-0x08A5,-1,itemlistwindowselected,2:4:8:12
-0x088C,19,wanttoconnection,2:6:10:14:18
-0x0895,26,partyinvite2,2
-//0x088F,4 // CZ_GANGSI_RANK
-0x08AB,26,friendslistadd,2
-0x0960,5,hommenu,2:4
-0x0930,36,storagepassword,2:4:20
-
-//2013-07-03Ragexe
-packet_ver: 42
-packet_keys: 0x4FF90E23,0x0F1432F2,0x4CFA1EDA // [Shakto]
-0x0369,7,actionrequest,2:6
-0x083C,10,useskilltoid,2:4:6
-0x0437,5,walktoxy,2
-0x035F,6,ticksend,2
-0x0930,5,changedir,2:4
-0x07E4,6,takeitem,2
-0x0362,6,dropitem,2:4
-0x07EC,8,movetokafra,2:4
-0x0364,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x096A,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0835,2,searchstoreinfonextpage,0
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0202,6,reqclickbuyingstore,2
-0x0817,2,reqclosebuyingstore,0
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x0365,18,bookingregreq,2:4:6
-//0x0363,8 // CZ_JOIN_BATTLE_FIELD
-0x0281,-1,itemlistwindowselected,2:4:8:12
-0x022D,19,wanttoconnection,2:6:10:14:18
-0x0802,26,partyinvite2,2
-//0x0436,4 // CZ_GANGSI_RANK
-0x0360,26,friendslistadd,2
-0x094A,5,hommenu,2:4
-0x0873,36,storagepassword,2:4:20
-
-//2013-07-10Ragexe
-packet_ver: 43
-packet_keys: 0x458F758F,0x4CCF3F8F,0x4A9C4237
-0x0369,7,actionrequest,2:6
-0x083C,10,useskilltoid,2:4:6
-0x0437,5,walktoxy,2
-0x035F,6,ticksend,2
-0x0202,5,changedir,2:4
-0x07E4,6,takeitem,2
-0x0362,6,dropitem,2:4
-0x07EC,8,movetokafra,2:4
-0x0364,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x096A,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0835,2,searchstoreinfonextpage,0
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0360,6,reqclickbuyingstore,2
-0x0817,2,reqclosebuyingstore,0
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x0365,18,bookingregreq,2:4:6
-//0x0363,8 // CZ_JOIN_BATTLE_FIELD
-0x0281,-1,itemlistwindowselected,2:4:8:12
-0x022D,19,wanttoconnection,2:6:10:14:18
-0x0802,26,partyinvite2,2
-//0x0436,4 // CZ_GANGSI_RANK
-0x023B,26,friendslistadd,2
-0x0361,5,hommenu,2:4
-0x0880,36,storagepassword,2:4:20
-0x0848,-1,cashshopbuy,2:6:4:10
-0x097D,288 //ZC_ACK_RANKING
-
-//2013-07-17Ragexe
-packet_ver: 44
-packet_keys: 0x2BED4F91,0x5F9E00CF,0x5EE5520C
-0x0918,7,actionrequest,2:6
-0x091E,10,useskilltoid,2:4:6
-0x083C,5,walktoxy,2
-0x02C4,6,ticksend,2
-0x088C,5,changedir,2:4
-0x08A9,6,takeitem,2
-0x0917,6,dropitem,2:4
-0x089B,8,movetokafra,2:4
-0x0956,8,movefromkafra,2:4
-0x0882,10,useskilltopos,2:4:6:8
-0x0952,90,useskilltoposinfo,2:4:6:8:10
-0x0958,6,getcharnamerequest,2
-0x0967,6,solvecharname,2
-0x0960,12,searchstoreinfolistitemclick,2:6:10
-0x0819,2,searchstoreinfonextpage,0
-0x086B,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x093B,-1,reqtradebuyingstore,2:4:8:12
-0x0898,6,reqclickbuyingstore,2
-0x096A,2,reqclosebuyingstore,0
-0x08AA,-1,reqopenbuyingstore,2:4:8:9:89
-0x0862,18,bookingregreq,2:4:6
-//0x08A6,8 // CZ_JOIN_BATTLE_FIELD
-0x0897,-1,itemlistwindowselected,2:4:8:12
-0x091D,19,wanttoconnection,2:6:10:14:18
-0x092F,26,partyinvite2,2
-//0x086C,4 // CZ_GANGSI_RANK
-0x0863,26,friendslistadd,2
-0x088A,5,hommenu,2:4
-0x095B,36,storagepassword,2:4:20
-0x09A6,12,ZC_BANKING_CHECK,2:10
-0x09A7,10,bankdeposit,2:6
-0x09A8,16,ZC_ACK_BANKING_DEPOSIT,2:4:12
-0x09A9,10,bankwithdrawal,2:6
-0x09AA,16,ZC_ACK_BANKING_WITHDRAW,2:4:12
-0x09AB,6,bankcheck,2
-0x09B6,6,bankopen,2
-0x09B7,4,ZC_ACK_OPEN_BANKING,2
-0x09B8,6,bankclose,2
-0x09B9,4,ZC_ACK_CLOSE_BANKING,2
-
-//2013-07-31cRagexe
-0x09ca,23 // ZC_SKILL_ENTRY5
-0x09cb,17	// ZC_USE_SKILL2
-
-//2013-08-07Ragexe
-packet_ver: 45
-packet_keys: 0x7E241DE0,0x5E805580,0x3D807D80 // [Shakto]
-0x0369,7,actionrequest,2:6
-0x083C,10,useskilltoid,2:4:6
-0x0437,5,walktoxy,2
-0x035F,6,ticksend,2
-0x0202,5,changedir,2:4
-0x07E4,6,takeitem,2
-0x0362,6,dropitem,2:4
-0x07EC,8,movetokafra,2:4
-0x0364,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x096A,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0835,2,searchstoreinfonextpage,0
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0360,6,reqclickbuyingstore,2
-0x0817,2,reqclosebuyingstore,0
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x0365,18,bookingregreq,2:4:6
-//0x363,8 // CZ_JOIN_BATTLE_FIELD
-0x0281,-1,itemlistwindowselected,2:4:8:12
-0x022D,19,wanttoconnection,2:6:10:14:18
-0x0802,26,partyinvite2,2
-//0x436,4 // CZ_GANGSI_RANK
-0x023B,26,friendslistadd,2
-0x0361,5,hommenu,2:4
-0x0887,36,storagepassword,2:4:20
-0x09C1,10,ZC_C_MARKERINFO,2:6:8
-// Merge Item
-0x096D,-1,ZC_MERGE_ITEM_OPEN,2:4 // ZC_MERGE_ITEM_OPEN
-0x096E,-1,mergeitem_req,2:4 // CZ_REQ_MERGE_ITEM
-0x096F,7,ZC_ACK_MERGE_ITEM,2:4:6:7 // ZC_ACK_MERGE_ITEM
-0x0974,2,mergeitem_cancel,0 // CZ_CANCEL_MERGE_ITEM
-
-//2013-12-23Ragexe
-packet_ver: 46
-packet_keys: 0x631C511C,0x111C111C,0x111C111C // [Shakto]
-0x0369,7,actionrequest,2:6
-0x083C,10,useskilltoid,2:4:6
-0x0437,5,walktoxy,2
-0x035F,6,ticksend,2
-0x0202,5,changedir,2:4
-0x07E4,6,takeitem,2
-0x0362,6,dropitem,2:4
-0x07EC,8,movetokafra,2:4
-0x0364,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x096A,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0835,2,searchstoreinfonextpage,0
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0360,6,reqclickbuyingstore,2
-0x0817,2,reqclosebuyingstore,0
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x0365,18,bookingregreq,2:4:6
-//0x363,8 // CZ_JOIN_BATTLE_FIELD
-0x0281,-1,itemlistwindowselected,2:4:8:12
-0x022D,19,wanttoconnection,2:6:10:14:18
-0x0802,26,partyinvite2,2
-//0x436,4 // CZ_GANGSI_RANK
-0x023B,26,friendslistadd,2
-0x0361,5,hommenu,2:4
-0x08A4,36,storagepassword,2:4:20
-//New Packets
-//0x097E,12 //ZC_UPDATE_RANKING_POINT
-0x09CE,102,itemmonster,2
-0x09D4,2,npcshopclosed,0
-//NPC Market
-0x09D5,-1
-0x09D6,-1,npcmarketpurchase,2:4:6
-0x09D7,-1
-0x09D8,2,npcmarketclosed,0
-// Clan System
-0x0988,6
-0x0989,2
-0x098A,-1
-0x098D,-1,clanchat,2:4
-0x098E,-1
-// Sale
-0x09AC,-1,salesearch,2:4:8
-0x09AD,8
-0x09AE,17,saleadd,2:6:8:12:16
-0x09AF,4
-0x09B0,8,saleremove,2:6
-0x09B1,4
-0x09B2,8
-0x09B3,4
-0x09B4,6,saleopen,2
-0x09BC,6,saleclose,2
-0x09C3,8,salerefresh,2:6
-0x09C4,8
-
-// New Packet
-0x097A,-1		// ZC_ALL_QUEST_LIST2
-0x09DB,-1		// ZC_NOTIFY_MOVEENTRY10
-0x09DC,-1		// ZC_NOTIFY_NEWENTRY10
-0x09DD,-1	// ZC_NOTIFY_STANDENTRY10
-0x09DF,7		// ZC_ACK_WHISPER02
-
-//2014-10-16Ragexe
-packet_ver: 50
-packet_keys: 0x2DFF467C,0x444B37EE,0x2C1B634F // [YomRawr]
-0x0369,7,actionrequest,2:6
-0x083C,10,useskilltoid,2:4:6
-0x0437,5,walktoxy,2
-0x035F,6,ticksend,2
-0x0967,5,changedir,2:4
-0x07E4,6,takeitem,2
-0x0362,6,dropitem,2:4
-0x07EC,8,movetokafra,2:4
-0x022D,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x096A,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0835,2,searchstoreinfonextpage,0
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0360,6,reqclickbuyingstore,2
-0x0817,2,reqclosebuyingstore,0
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x0365,18,bookingregreq,2:4
-// 0x0363,8 // CZ_JOIN_BATTLE_FIELD
-0x0281,-1,itemlistwindowselected,2:4:8
-0x086E,19,wanttoconnection,2:6:10:14:18
-0x0802,26,partyinvite,2
-// 0x0922,4 // CZ_GANGSI_RANK
-0x094B,26,friendslistadd,2
-0x0364,5,hommenu,2:4
-0x0936,36,storagepassword,0
-0x09DF,7
-
-// New packet
-0x0A00,269		// ZC_SHORTCUT_KEY_LIST_V3
-0x0A01,3,hotkeyrowshift,2	// CZ_SHORTCUTKEYBAR_ROTATE
-0x0A02,4			// ZC_DRESSROOM_OPEN
-0x0A0E,14		// ZC_BATTLEFIELD_NOTIFY_HP2
-0x09F7,75		// ZC_PROPERTY_HOMUN_2
-0x09E5,18		// ZC_DELETEITEM_FROM_MCSTORE2
-0x09E6,22		// ZC_UPDATE_ITEM_FROM_BUYING_STORE2
-
-// Roulette System [Yommy]
-0x0A19,2,rouletteopen,0	// CZ_REQ_OPEN_ROULETTE
-0x0A1A,23 		// ZC_ACK_OPEN_ROULETTE
-0x0A1B,2,rouletteinfo,0 	// CZ_REQ_ROULETTE_INFO
-0x0A1C,-1 		// ZC_ACK_ROULETTE_INFO
-0x0A1D,2,rouletteclose,0 	// CZ_REQ_CLOSE_ROULETTE
-0x0A1E,3 			// ZC_ACK_CLOSE_ROULETTE
-0x0A1F,2,roulettegenerate,0 	// CZ_REQ_GENERATE_ROULETTE
-0x0A20,21 		// ZC_ACK_GENERATE_ROULETTE
-0x0A21,3,rouletterecvitem,2 	// CZ_RECV_ROULETTE_ITEM
-0x0A22,5 			// ZC_RECV_ROULETTE_ITEM
-
-//2014-10-22bRagexe
-packet_ver: 51
-packet_keys: 0x290551EA,0x2B952C75,0x2D67669B // [YomRawr]
-0x006d,149
-0x023b,10,useskilltopos,2:4:6:8
-0x0281,-1,itemlistwindowselected,2:4:8:12
-0x035f,6,ticksend,2
-0x0360,6,reqclickbuyingstore,2
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x0368,6,solvecharname,2
-0x0369,7,actionrequest,2:6
-0x0437,5,walktoxy,2
-0x0438,36,storagepassword,2:4:20
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x0817,2,reqclosebuyingstore,0
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0835,12,searchstoreinfolistitemclick,2:6:10
-0x083c,10,useskilltoid,2:4:6
-0x0878,8,movetokafra,2:4
-0x087d,6,dropitem,2:4
-0x0896,26,partyinvite2,2
-0x0899,5,hommenu,2:4
-0x08aa,8,movefromkafra,2:4
-//0x08ab,4	// CZ_GANGSI_RANK
-0x08ad,5,changedir,2:4
-0x08e3,149
-0x091a,26,friendslistadd,2
-//0x092b,8	// CZ_JOIN_BATTLE_FIELD
-0x093b,19,wanttoconnection,2:6:10:14:18
-0x0940,2,searchstoreinfonextpage,0
-0x094e,6,takeitem,2
-0x0955,18,bookingregreq,2:4:6
-0x096a,6,getcharnamerequest,2
-
-// New Packet
-0x0A18,14		// ZC_ACCEPT_ENTER3
-0x0A28,3		// ZC_ACK_OPENSTORE2
-0x09FD,-1		// ZC_NOTIFY_MOVEENTRY11
-0x09FE,-1		// ZC_NOTIFY_NEWENTRY11
-0x09FF,-1		// ZC_NOTIFY_STANDENTRY11
-//0x09F8,-1		// ZC_ALL_QUEST_LIST3
-
-//2015-05-13aRagexe
-packet_ver: 52
-packet_keys: 0x62C86D09,0x75944F17,0x112C133D // [YomRawr]
-0x0369,7,actionrequest,2:6
-0x083C,10,useskilltoid,2:4:6
-0x0437,5,walktoxy,2
-0x035F,6,ticksend,2
-0x0924,5,changedir,2:4
-0x0958,6,takeitem,2
-0x0885,6,dropitem,2:4
-0x0879,8,movetokafra,2:4
-0x0864,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x096A,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0835,2,searchstoreinfonextpage,0
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0360,6,reqclickbuyingstore,2
-0x022D,2,reqclosebuyingstore,0
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x0883,18,bookingregreq,2:4:6
-// 0x02C4,8 CZ_JOIN_BATTLE_FIELD
-0x0960,-1,itemlistwindowselected,2:4:8:12
-0x0363,19,wanttoconnection,2:6:10:14:18
-0x094A,26,partyinvite2,2
-// 0x0927,4 CZ_GANGSI_RANK
-0x08A8,26,friendslistadd,2
-0x0817,5,hommenu,2:4
-0x0923,36,storagepassword,2:4:20
-
-// New Packets
-0xA3B,-1		// ZC_HAT_EFFECT
-
-// RODEX Mail system
-0x09E7,3		// ZC_NOTIFY_UNREADMAIL
-0x09E8,11,mailrefresh,2:3	// CZ_OPEN_MAILBOX
-0x09E9,2,dull,0 	// CZ_CLOSE_MAILBOX
-0x09EA,11,mailread,2:3	// CZ_REQ_READ_MAIL
-0x09EB,-1		// ZC_ACK_READ_MAIL
-0x09EC,-1,mailsend,2:4:28:52:60:62:64	// CZ_REQ_WRITE_MAIL
-0x09ED,3		// ZC_ACK_WRITE_MAIL
-0x09EE,11,mailrefresh,2:3	// CZ_REQ_NEXT_MAIL_LIST
-0x09EF,11,mailrefresh,2:3 	// CZ_REQ_REFRESH_MAIL_LIST
-0x09F0,-1		// ZC_ACK_MAIL_LIST
-0x09F1,11,mailgetattach,0	// CZ_REQ_ZENY_FROM_MAIL
-0x09F2,12	// ZC_ACK_ZENY_FROM_MAIL
-0x09F3,11,mailgetattach,0	// CZ_REQ_ITEM_FROM_MAIL
-0x09F4,12	// ZC_ACK_ITEM_FROM_MAIL
-0x09F5,11,maildelete,0	// CZ_REQ_DELETE_MAIL
-0x09F6,11		// ZC_ACK_DELETE_MAIL
-0x0A03,2,mailcancel,0	// CZ_REQ_CANCEL_WRITE_MAIL
-0x0A04,6,mailsetattach,2:4	// CZ_REQ_ADD_ITEM_TO_MAIL
-0x0A05,53	// ZC_ACK_ADD_ITEM_TO_MAIL
-0x0A06,6,mailwinopen,2:4	// CZ_REQ_REMOVE_ITEM_MAIL
-0x0A07,9		// ZC_ACK_REMOVE_ITEM_MAIL
-0x0A08,26,mailbegin,0	// CZ_REQ_OPEN_WRITE_MAIL
-0x0A12,27	// ZC_ACK_OPEN_WRITE_MAIL
-0x0A13,26,mailreceiver,2	// CZ_CHECK_RECEIVE_CHARACTER_NAME
-0x0A14,10		// ZC_CHECK_RECEIVE_CHARACTER_NAME
-0x0A32,2		// ZC_OPEN_RODEX_THROUGH_NPC_ONLY
-
-// New EquipPackets Support
-0x0A09,45	// ZC_ADD_EXCHANGE_ITEM3
-0x0A0A,47	// ZC_ADD_ITEM_TO_STORE3
-0x0A0B,47	// ZC_ADD_ITEM_TO_CART3
-0x0A0C,56	// ZC_ITEM_PICKUP_ACK_V6
-0x0A0D,-1	// ZC_INVENTORY_ITEMLIST_EQUIP_V6
-0x0A0F,-1		// ZC_CART_ITEMLIST_EQUIP_V6
-0x0A10,-1		// ZC_STORE_ITEMLIST_EQUIP_V6
-0x0A2D,-1	// ZC_EQUIPWIN_MICROSCOPE_V6
-
-// OneClick Itemidentify
-0x0A35,4,oneclick_itemidentify,2	// CZ_REQ_ONECLICK_ITEMIDENTIFY
-
-// Achievement System
-0x0A23,-1		// ZC_ALL_ACH_LIST
-0x0A24,66	// ZC_ACH_UPDATE
-0x0A25,6,dull,0	// CZ_REQ_ACH_REWARD
-0x0A26,7		// ZC_REQ_ACH_REWARD_ACK
-
-// Title System
-0x0A2E,6,dull,0	// CZ_REQ_CHANGE_TITLE
-0x0A2F,7		// ZC_ACK_CHANGE_TITLE
-0x0A30,106	// ZC_ACK_REQNAMEALL2
-
-// Pet Evolution System
-0x09FB,-1,dull,0	// CZ_PET_EVOLUTION
-0x09FC,6		// ZC_PET_EVOLUTION_RESULT
-
-//2015-05-20aRagexe
-0x0A3D,18,saleadd,2:6:8:12:16
-
-//2015-09-16Ragexe
-packet_ver: 53
-packet_keys: 0x17F83A19,0x116944F4,0x1CC541E9 // [Napster]
-0x0869,7,actionrequest,2:6
-0x093E,10,useskilltoid,2:4:6
-0x0877,5,walktoxy,2
-0x08AC,6,ticksend,2
-0x0936,5,changedir,2:4
-0x089C,6,takeitem,2
-0x092F,6,dropitem,2:4
-0x0934,8,movetokafra,2:4
-0x085E,8,movefromkafra,2:4
-0x022D,10,useskilltopos,2:4:6:8
-0x0873,90,useskilltoposinfo,2:4:6:8:10
-0x095A,6,getcharnamerequest,2
-0x0942,6,solvecharname,2
-0x087F,12,searchstoreinfolistitemclick,2:6:10
-0x0817,2,searchstoreinfonextpage,0
-0x0920,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0881,-1,reqtradebuyingstore,2:4:8:12
-0x0835,6,reqclickbuyingstore,2
-0x092E,2,reqclosebuyingstore,0
-0x0948,-1,reqopenbuyingstore,2:4:8:9:89
-0x089B,18,bookingregreq,2:4:6
-// 0x094F,8 CZ_JOIN_BATTLE_FIELD
-0x0961,-1,itemlistwindowselected,2:4:8:12
-0x0969,19,wanttoconnection,2:6:10:14:18
-0x0924,26,partyinvite2,2
-// 0x0938,4 CZ_GANGSI_RANK
-0x089E,26,friendslistadd,2
-0x0960,5,hommenu,2:4
-0x0941,36,storagepassword,2:4:20
-
-// New Packet
-0x097F,-1		// ZC_SELECTCART
-0x0980,7,selectcart,2:6	// CZ_SELECTCART
-
-//2015-10-01bRagexeRE
-packet_ver: 54
-packet_keys: 0x45B945B9,0x45B945B9,0x45B945B9	// [Dastgir]
-0x0369,7,actionrequest,2:6
-0x083c,10,useskilltoid,2:4:6
-0x0437,5,walktoxy,2
-0x035f,6,ticksend,2
-0x0202,5,changedir,2:4
-0x07e4,6,takeitem,2
-0x0362,6,dropitem,2:4
-0x07ec,8,movetokafra,2:4
-0x0364,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposmoreinfo,2:4:6:8:10
-0x096a,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0835,2,searchstoreinfonextpage,0
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0811,-1,reqtradebuyingstore,2:4:8:12
-0x0360,6,reqclickbuyingstore,2
-0x0817,2,reqclosebuyingstore,0
-0x0815,-1,reqopenbuyingstore,2:4:8:9:89
-0x0365,18,partybookingregisterreq,2:4:6
-//0x0363,8 // CZ_JOIN_BATTLE_FIELD
-0x0281,-1,itemlistwindowselected,2:4:8:12
-0x022d,19,wanttoconnection,2:6:10:14:18
-0x0802,26,partyinvite2,2
-//0x0436,4 // CZ_GANGSI_RANK
-0x023b,26,friendslistadd,2
-0x0361,5,hommenu,2:4
-0x0860,36,storagepassword,2:4:20
-
-//2015-11-04aRagexe
-packet_ver: 55
-packet_keys: 0x4C17382A,0x7ED174C9,0x29961E4F // [Winnie]
-0x0369,7,actionrequest,2:6
-0x083C,10,useskilltoid,2:4:6
-0x0363,5,walktoxy,2
-0x0886,6,ticksend,2
-0x0928,5,changedir,2:4
-0x0964,6,takeitem,2
-0x0437,6,dropitem,2:4
-0x088B,8,movetokafra,2:4
-0x0364,8,movefromkafra,2:4
-0x0438,10,useskilltopos,2:4:6:8
-0x0366,90,useskilltoposinfo,2:4:6:8:10
-0x0887,6,getcharnamerequest,2
-0x0368,6,solvecharname,2
-0x0838,12,searchstoreinfolistitemclick,2:6:10
-0x0835,2,searchstoreinfonextpage,0
-0x0819,-1,searchstoreinfo,2:4:5:9:13:14:15
-0x0815,-1,reqtradebuyingstore,2:4:8:12
-0x0436,6,reqclickbuyingstore,2
-0x0817,2,reqclosebuyingstore,0
-0x023B,-1,reqopenbuyingstore,2:4:8:9:89
-0x0811,18,bookingregreq,2:4:6
-//0x0939,8 CZ_JOIN_BATTLE_FIELD
-0x093A,-1,itemlistwindowselected,2:4:8:12
-0x0360,19,wanttoconnection,2:6:10:14:18
-0x08A5,26,partyinvite2,2
-//0x08A3,4 CZ_GANGSI_RANK
-0x07EC,26,friendslistadd,2
-0x088D,5,hommenu,2:4
-0x0940,36,storagepassword,2:4:20
-
-// 2016-03-02bRagexe
-0x0A51,34
-
-// 2016-03-30aRagexe
-0x0A6E,-1,mailsend,2:4:28:52:60:62:64:68	// CZ_REQ_WRITE_MAIL2
-
-// 2016-06-01aRagexe
-0x0A7D,-1
-
-// 2017-05-02dRagexeRE
-0x0A43,85
-0x0A44,-1
-0x0ABD,10
-
-//Add new packets here
-//packet_ver: 56

+ 2407 - 0
db/pre-re/achievement_db.yml

@@ -0,0 +1,2407 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2017 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 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/>.
+#
+###########################################################################
+# Custom Achievement Database
+###########################################################################
+#
+# Achievement Settings
+#
+###########################################################################
+# ID - Unique achievement ID.
+###########################################################################
+# Group - Achievement group type. Each achievement type calls a specific
+# objective check.
+# Valid groups:
+#  AG_ADD_FRIEND
+#  AG_ADVENTURE
+#  AG_BABY
+#  AG_BATTLE
+#  AG_CHATTING
+#  AG_CHATTING_COUNT
+#  AG_CHATTING_CREATE
+#  AG_CHATTING_DYING
+#  AG_EAT
+#  AG_GET_ITEM
+#  AG_GET_ZENY
+#  AG_GOAL_ACHIEVE
+#  AG_GOAL_LEVEL
+#  AG_GOAL_STATUS
+#  AG_HEAR
+#  AG_JOB_CHANGE
+#  AG_MARRY
+#  AG_PARTY
+#  AG_ENCHANT_FAIL
+#  AG_ENCHANT_SUCCESS
+#  AG_SEE
+#  AG_SPEND_ZENY
+#  AG_TAMING
+###########################################################################
+# Name - Achievement name. Used when sending rewards through RODEX.
+###########################################################################
+# Target - A list of monster ID and count values that the achievement
+# requires. The target count can also be used for achievements that keep
+# a counter while not being related to monster kills.
+# Capped at MAX_ACHIEVEMENT_OBJECTIVES.
+###########################################################################
+# Condition - A conditional statement that must be met for the achievement
+# to be considered complete.
+###########################################################################
+# Map - A map name that is used for the AG_CHATTING type which increments
+# the counter based on the player's map.
+###########################################################################
+# Dependent: - A list of achievement IDs that need to be completed before
+# this achievement is considered complete.
+###########################################################################
+# Reward - A list of rewards that are given on completion. All fields are
+# optional.
+#   ItemID: Item ID
+#   Amount:  Amount of Item ID (default 1)
+#   Script: Bonus Script
+#   TitleID: Title ID
+###########################################################################
+# Score - Achievement points that are given on completion.
+###########################################################################
+
+Achievements:
+  - ID: 110000
+    Group: "AG_EAT"
+    Name: "At this time I live to eat"
+    Score: 10
+  - ID: 110001
+    Group: "AG_SEE"
+    Name: "A fan of this polarity"
+    Score: 10
+  - ID: 120001
+    Group: "AG_ADVENTURE"
+    Name: "North Prontera Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120002
+    Group: "AG_ADVENTURE"
+    Name: "North Prontera Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120003
+    Group: "AG_ADVENTURE"
+    Name: "North Prontera Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120004
+    Group: "AG_ADVENTURE"
+    Name: "West Prontera Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120005
+    Group: "AG_ADVENTURE"
+    Name: "West Prontera Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120006
+    Group: "AG_ADVENTURE"
+    Name: "East Prontera Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120007
+    Group: "AG_ADVENTURE"
+    Name: "South Prontera Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120008
+    Group: "AG_ADVENTURE"
+    Name: "South Prontera Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120009
+    Group: "AG_ADVENTURE"
+    Name: "South Prontera Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120010
+    Group: "AG_ADVENTURE"
+    Name: "South Prontera Field Exploration(4)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120011
+    Group: "AG_ADVENTURE"
+    Name: "East Geffen Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120012
+    Group: "AG_ADVENTURE"
+    Name: "Southeast Geffen Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120013
+    Group: "AG_ADVENTURE"
+    Name: "Northwest Geffen Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120014
+    Group: "AG_ADVENTURE"
+    Name: "Northwest Geffen Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120015
+    Group: "AG_ADVENTURE"
+    Name: "Northwest Geffen Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120016
+    Group: "AG_ADVENTURE"
+    Name: "South Geffen Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120017
+    Group: "AG_ADVENTURE"
+    Name: "South Geffen Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120018
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120019
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120020
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120021
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Field Exploration(4)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120022
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Field Exploration(5)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120023
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Field Exploration(6)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120024
+    Group: "AG_ADVENTURE"
+    Name: "Southwest Payon Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120025
+    Group: "AG_ADVENTURE"
+    Name: "Southwest Payon Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120026
+    Group: "AG_ADVENTURE"
+    Name: "Southwest Payon Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120027
+    Group: "AG_ADVENTURE"
+    Name: "Southwest Payon Field Exploration(4)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120028
+    Group: "AG_ADVENTURE"
+    Name: "East Payon Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120029
+    Group: "AG_ADVENTURE"
+    Name: "East Payon Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120030
+    Group: "AG_ADVENTURE"
+    Name: "East Payon Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120031
+    Group: "AG_ADVENTURE"
+    Name: "East Payon Field Exploration(4)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120032
+    Group: "AG_ADVENTURE"
+    Name: "North Mjolnir Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120033
+    Group: "AG_ADVENTURE"
+    Name: "North Mjolnir Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120034
+    Group: "AG_ADVENTURE"
+    Name: "North Mjolnir Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120035
+    Group: "AG_ADVENTURE"
+    Name: "North Mjolnir Field Exploration(4)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120036
+    Group: "AG_ADVENTURE"
+    Name: "North Mjolnir Field Exploration(5)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120037
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120038
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120039
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120040
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Field Exploration(4)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120041
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Field Exploration(5)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120042
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Field Exploration(6)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120043
+    Group: "AG_ADVENTURE"
+    Name: "South Aldebaran Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120044
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120045
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120046
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120047
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(4)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120048
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(5)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120049
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(6)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120050
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(7)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120051
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(8)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120052
+    Group: "AG_ADVENTURE"
+    Name: "Border Checkpoint Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120053
+    Group: "AG_ADVENTURE"
+    Name: "Border Checkpoint Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120054
+    Group: "AG_ADVENTURE"
+    Name: "Kiel Hyre Mansion Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120055
+    Group: "AG_ADVENTURE"
+    Name: "El Mes Plateau Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120056
+    Group: "AG_ADVENTURE"
+    Name: "El Mes Plateau Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120057
+    Group: "AG_ADVENTURE"
+    Name: "El Mes Plateau Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120058
+    Group: "AG_ADVENTURE"
+    Name: "El Mes Gorge Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120059
+    Group: "AG_ADVENTURE"
+    Name: "Kiel Hyre Academy Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120060
+    Group: "AG_ADVENTURE"
+    Name: "Guard Camp Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120061
+    Group: "AG_ADVENTURE"
+    Name: "Yuno Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120062
+    Group: "AG_ADVENTURE"
+    Name: "Front of Thanatos Tower Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120063
+    Group: "AG_ADVENTURE"
+    Name: "Hugel Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120064
+    Group: "AG_ADVENTURE"
+    Name: "Hugel Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120065
+    Group: "AG_ADVENTURE"
+    Name: "Hugel Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120066
+    Group: "AG_ADVENTURE"
+    Name: "Abyss Lake Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120067
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120068
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120069
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120070
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(4)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120071
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(5)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120072
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(6)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120073
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(7)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120074
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(8)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120075
+    Group: "AG_ADVENTURE"
+    Name: "Lighthalzen Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120076
+    Group: "AG_ADVENTURE"
+    Name: "Lighthalzen Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120077
+    Group: "AG_ADVENTURE"
+    Name: "Lighthalzen Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120078
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Audhumbla Plains Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120079
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Plains Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120080
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Plains Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120081
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Plains Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120082
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Audhumbla Grassland Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120083
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Audhumbla Grassland Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120084
+    Group: "AG_ADVENTURE"
+    Name: "Portus Luna Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120085
+    Group: "AG_ADVENTURE"
+    Name: "Veins Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120086
+    Group: "AG_ADVENTURE"
+    Name: "Veins Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120087
+    Group: "AG_ADVENTURE"
+    Name: "Veins Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120088
+    Group: "AG_ADVENTURE"
+    Name: "Veins Field Exploration(4)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120089
+    Group: "AG_ADVENTURE"
+    Name: "Veins Field Exploration(5)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120090
+    Group: "AG_ADVENTURE"
+    Name: "Eclage Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120091
+    Group: "AG_ADVENTURE"
+    Name: "North Bitfrost Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120092
+    Group: "AG_ADVENTURE"
+    Name: "South Bitfrost Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120093
+    Group: "AG_ADVENTURE"
+    Name: "Splendide Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120094
+    Group: "AG_ADVENTURE"
+    Name: "Splendide Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120095
+    Group: "AG_ADVENTURE"
+    Name: "Splendide Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120096
+    Group: "AG_ADVENTURE"
+    Name: "Manuk Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120097
+    Group: "AG_ADVENTURE"
+    Name: "Manuk Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120098
+    Group: "AG_ADVENTURE"
+    Name: "Manuk Field Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120099
+    Group: "AG_ADVENTURE"
+    Name: "Outskirts of Kamidal Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120100
+    Group: "AG_ADVENTURE"
+    Name: "Outskirts of Kamidal Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120101
+    Group: "AG_ADVENTURE"
+    Name: "Amatsu Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120102
+    Group: "AG_ADVENTURE"
+    Name: "Kunlun Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120103
+    Group: "AG_ADVENTURE"
+    Name: "Gonryun Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120104
+    Group: "AG_ADVENTURE"
+    Name: "Ayothaya Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120105
+    Group: "AG_ADVENTURE"
+    Name: "Moscovia Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120106
+    Group: "AG_ADVENTURE"
+    Name: "Brasilis Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120107
+    Group: "AG_ADVENTURE"
+    Name: "Dewata Field Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120108
+    Group: "AG_ADVENTURE"
+    Name: "Malaya Field Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120109
+    Group: "AG_ADVENTURE"
+    Name: "Malaya Field Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 10
+  - ID: 120110
+    Group: "AG_ADVENTURE"
+    Name: "Abbey Underground Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120111
+    Group: "AG_ADVENTURE"
+    Name: "Abyss Lake Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120112
+    Group: "AG_ADVENTURE"
+    Name: "Clock Tower Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120113
+    Group: "AG_ADVENTURE"
+    Name: "Amatsu Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120114
+    Group: "AG_ADVENTURE"
+    Name: "Ant Hell Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120115
+    Group: "AG_ADVENTURE"
+    Name: "Ayothaya Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120116
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120117
+    Group: "AG_ADVENTURE"
+    Name: "Brasilis Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120118
+    Group: "AG_ADVENTURE"
+    Name: "Clock Tower Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120119
+    Group: "AG_ADVENTURE"
+    Name: "Istana Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120120
+    Group: "AG_ADVENTURE"
+    Name: "Scaraba Hole Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120121
+    Group: "AG_ADVENTURE"
+    Name: "Bitfrost Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120122
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120123
+    Group: "AG_ADVENTURE"
+    Name: "Geffen Underground Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120124
+    Group: "AG_ADVENTURE"
+    Name: "Glastheim Dungeon Exploration(1)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120125
+    Group: "AG_ADVENTURE"
+    Name: "Glastheim Dungeon Exploration(2)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120126
+    Group: "AG_ADVENTURE"
+    Name: "Glastheim Dungeon Exploration(3)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120127
+    Group: "AG_ADVENTURE"
+    Name: "Glastheim Dungeon Exploration(4)"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120128
+    Group: "AG_ADVENTURE"
+    Name: "Kunlun Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120129
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120130
+    Group: "AG_ADVENTURE"
+    Name: "Sphinx Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120131
+    Group: "AG_ADVENTURE"
+    Name: "Izlude Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120132
+    Group: "AG_ADVENTURE"
+    Name: "Robot Factory Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120133
+    Group: "AG_ADVENTURE"
+    Name: "Bio Lab Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120134
+    Group: "AG_ADVENTURE"
+    Name: "Gonryun Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120135
+    Group: "AG_ADVENTURE"
+    Name: "Nogg Road Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120136
+    Group: "AG_ADVENTURE"
+    Name: "Coal Mine Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120137
+    Group: "AG_ADVENTURE"
+    Name: "Pyramid Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120138
+    Group: "AG_ADVENTURE"
+    Name: "Orc Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120139
+    Group: "AG_ADVENTURE"
+    Name: "Payon Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120140
+    Group: "AG_ADVENTURE"
+    Name: "Labyrinth Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120141
+    Group: "AG_ADVENTURE"
+    Name: "Undersea Tunnel Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120142
+    Group: "AG_ADVENTURE"
+    Name: "Thanatos Tower Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120143
+    Group: "AG_ADVENTURE"
+    Name: "Thor Volcano Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120144
+    Group: "AG_ADVENTURE"
+    Name: "Sunken Ship Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120145
+    Group: "AG_ADVENTURE"
+    Name: "Turtle Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 120146
+    Group: "AG_ADVENTURE"
+    Name: "Toy Factory Dungeon Exploration"
+    #Reward:
+    #  ItemID: 22876
+    Score: 20
+  - ID: 127001
+    Group: "AG_CHATTING"
+    Name: "Prontera Contribution"
+    Map: "prontera"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127002
+    Group: "AG_CHATTING"
+    Name: "Geffen Contribution"
+    Map: "geffen"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127003
+    Group: "AG_CHATTING"
+    Name: "Morocc Contribution"
+    Map: "morocc"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127004
+    Group: "AG_CHATTING"
+    Name: "Payon Contribution"
+    Map: "payon"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127005
+    Group: "AG_CHATTING"
+    Name: "Yuno Contribution"
+    Map: "yuno"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127006
+    Group: "AG_CHATTING"
+    Name: "Lighthalzen Contribution"
+    Map: "lighthalzen"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127007
+    Group: "AG_CHATTING"
+    Name: "Einbroch Contribution"
+    Map: "einbroch"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127008
+    Group: "AG_CHATTING"
+    Name: "Rachel Contribution"
+    Map: "rachel"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127009
+    Group: "AG_CHATTING"
+    Name: "Veins Contribution"
+    Map: "veins"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 128000
+    Group: "AG_BATTLE"
+    Name: "Uninvited Guest"
+    #Target:
+    #  - MobID: 2996
+    #    Count: 1
+    Score: 10
+  - ID: 128001
+    Group: "AG_BATTLE"
+    Name: "Strange Guest"
+    #Target:
+    #  - MobID: 2996
+    #    Count: 10
+    Score: 10
+  - ID: 128002
+    Group: "AG_BATTLE"
+    Name: "Get along with map..."
+    #Target:
+    #  - MobID: 2996
+    #    Count: 25
+    Score: 20
+  - ID: 128003
+    Group: "AG_BATTLE"
+    Name: "Welcomed Guest"
+    #Target:
+    #  - MobID: 2996
+    #    Count: 50
+    Score: 30
+  - ID: 128004
+    Group: "AG_BATTLE"
+    Name: "Kimmy's best friend"
+    #Target:
+    #  - MobID: 2996
+    #    Count: 100
+    Score: 50
+  - ID: 128005
+    Group: "AG_BATTLE"
+    Name: "Novice Angler"
+    #Target:
+    #  - MobID: 2322
+    #    Count: 1
+    Score: 10
+  - ID: 128006
+    Group: "AG_BATTLE"
+    Name: "Juicy Hunter"
+    #Target:
+    #  - MobID: 2322
+    #    Count: 10
+    Score: 20
+  - ID: 128007
+    Group: "AG_BATTLE"
+    Name: "Rhythm Master"
+    #Target:
+    #  - MobID: 2322
+    #    Count: 50
+    Score: 50
+  - ID: 128008
+    Group: "AG_BATTLE"
+    Name: "Bold Adventurer"
+    Target:
+      - MobID: 1929
+        Count: 1
+    Score: 10
+  - ID: 128009
+    Group: "AG_BATTLE"
+    Name: "Baphomet Hatred"
+    Target:
+      - MobID: 1929
+        Count: 10
+    Score: 20
+  - ID: 128010
+    Group: "AG_BATTLE"
+    Name: "Goat's Nemesis"
+    Target:
+      - MobID: 1929
+        Count: 50
+    Score: 50
+  - ID: 128011
+    Group: "AG_BATTLE"
+    Name: "Ordinary Tourist"
+    #Target:
+    #  - MobID: 3029
+    #    Count: 1
+    Score: 10
+  - ID: 128012
+    Group: "AG_BATTLE"
+    Name: "Backcountry Expert"
+    #Target:
+    #  - MobID: 3029
+    #    Count: 10
+    Score: 20
+  - ID: 128013
+    Group: "AG_BATTLE"
+    Name: "Able to eat more like this"
+    #Target:
+    #  - MobID: 3029
+    #    Count: 50
+    Score: 50
+  - ID: 128014
+    Group: "AG_BATTLE"
+    Name: "Digest hard meat"
+    #Target:
+    #  - MobID: 2319
+    #    Count: 1
+    Score: 10
+  - ID: 128015
+    Group: "AG_BATTLE"
+    Name: "Master of Escape"
+    #Target:
+    #  - MobID: 2319
+    #    Count: 10
+    Score: 20
+  - ID: 128016
+    Group: "AG_BATTLE"
+    Name: "Immortal Hunter"
+    #Target:
+    #  - MobID: 2319
+    #    Count: 50
+    Score: 50
+  - ID: 128017
+    Group: "AG_BATTLE"
+    Name: "Stood up and overcame despair"
+    #Target:
+    #  - MobID: 3097
+    #    Count: 1
+    Score: 10
+  - ID: 128018
+    Group: "AG_BATTLE"
+    Name: "Ember of Hope"
+    #Target:
+    #  - MobID: 3097
+    #    Count: 10
+    Score: 10
+  - ID: 128019
+    Group: "AG_BATTLE"
+    Name: "Pouring Aurora"
+    #Target:
+    #  - MobID: 3097
+    #    Count: 25
+    Score: 20
+  - ID: 128020
+    Group: "AG_BATTLE"
+    Name: "Who is desperate? I am hopeless!"
+    #Target:
+    #  - MobID: 3097
+    #    Count: 50
+    Score: 30
+  - ID: 128021
+    Group: "AG_BATTLE"
+    Name: "I know god will save the world"
+    #Target:
+    #  - MobID: 3097
+    #    Count: 100
+    Score: 50
+  - ID: 128022
+    Group: "AG_BATTLE"
+    Name: "There was mercy in Morocc army"
+    #Target:
+    #  - MobID: 3000
+    #  Count: 1
+    Score: 10
+  - ID: 128023
+    Group: "AG_BATTLE"
+    Name: "There was fear in Morocc army"
+    #Target:
+    #  - MobID: 3000
+    #    Count: 10
+    Score: 20
+  - ID: 128024
+    Group: "AG_BATTLE"
+    Name: "Guard of weak army"
+    #Target:
+    #  - MobID: 3000
+    #    Count: 50
+    Score: 50
+  - ID: 128025
+    Group: "AG_BATTLE"
+    Name: "Audience with the queen"
+    #Target:
+    #  - MobID: 2529
+    #    Count: 1
+    Score: 10
+  - ID: 128026
+    Group: "AG_BATTLE"
+    Name: "Warm earth"
+    #Target:
+    #  - MobID: 2533
+    #    Count: 1
+    Score: 10
+  - ID: 128027
+    Group: "AG_BATTLE"
+    Name: "Water is very good exactly"
+    #Target:
+    #  - MobID: 2534
+    #    Count: 1
+    Score: 10
+  - ID: 128028
+    Group: "AG_BATTLE"
+    Name: "Pleasant breeze"
+    #Target:
+    #  - MobID: 2535
+    #    Count: 1
+    Score: 10
+  - ID: 128029
+    Group: "AG_BATTLE"
+    Name: "Visitor of old castle"
+    #Target:
+    #  - MobID: 2476
+    #    Count: 1
+    Score: 10
+  - ID: 128030
+    Group: "AG_BATTLE"
+    Name: "Lord of old castle"
+    #Target:
+    #  - MobID: 2476
+    #    Count: 10
+    Score: 20
+  - ID: 128031
+    Group: "AG_BATTLE"
+    Name: "Conqueror of old castle"
+    #Target:
+    #  - MobID: 2476
+    #    Count: 50
+    Score: 50
+  - ID: 128032
+    Group: "AG_BATTLE"
+    Name: "Haggard sucker"
+    #Target:
+    #  - MobID: 3150
+    #    Count: 1
+    Score: 10
+  - ID: 128033
+    Group: "AG_BATTLE"
+    Name: "Hope of the Knight"
+    #Target:
+    #  - MobID: 3150
+    #    Count: 10
+    Score: 20
+  - ID: 128034
+    Group: "AG_BATTLE"
+    Name: "Guardian of the Dawn"
+    #Target:
+    #  - MobID: 3150
+    #    Count: 50
+    Score: 50
+  - ID: 128035
+    Group: "AG_BATTLE"
+    Name: "Time Traveler"
+    #Target:
+    #  - MobID: 3190
+    #    Count: 1
+    Score: 10
+  - ID: 128036
+    Group: "AG_BATTLE"
+    Name: "Restore ancient relic"
+    #Target:
+    #  - MobID: 3190
+    #    Count: 10
+    Score: 20
+  - ID: 128037
+    Group: "AG_BATTLE"
+    Name: "Master of relic transport"
+    #Target:
+    #  - MobID: 3190
+    #    Count: 50
+    Score: 50
+  - ID: 128038
+    Group: "AG_BATTLE"
+    Name: "Show Jailbreak to the captain"
+    #Target:
+    #  - MobID: 3181
+    #    Count: 1
+    Score: 10
+  - ID: 128039
+    Group: "AG_BATTLE"
+    Name: "Show Jailbreak to the weak captain"
+    #Target:
+    #  - MobID: 3188
+    #    Count: 1
+    Score: 10
+  - ID: 128040
+    Group: "AG_BATTLE"
+    Name: "Riot on board"
+    #Target:
+    #  - MobID: 3181
+    #    Count: 1
+    Score: 20
+  - ID: 128041
+    Group: "AG_BATTLE"
+    Name: "Turmoil on board"
+    #Target:
+    #  - MobID: 3181
+    #    Count: 10
+    Score: 20
+  - ID: 128042
+    Group: "AG_BATTLE"
+    Name: "Rebellion on board"
+    #Target:
+    #  - MobID: 3181
+    #    Count: 50
+    Score: 50
+  - ID: 128043
+    Group: "AG_BATTLE"
+    Name: "Revolt of Riot"
+    #Target:
+    #  - MobID: 3188
+    #    Count: 50
+    Score: 50
+  - ID: 128044
+    Group: "AG_BATTLE"
+    Name: "Magic tournament champion"
+    #Target:
+    #  - MobID: 2564
+    #    Count: 1
+    Score: 10
+  - ID: 128045
+    Group: "AG_BATTLE"
+    Name: "Gladiator of Coliseum"
+    #Target:
+    #  - MobID: 2564
+    #    Count: 10
+    Score: 20
+  - ID: 128046
+    Group: "AG_BATTLE"
+    Name: "Slayer of Colosseum"
+    #Target:
+    #  - MobID: 2564
+    #    Count: 50
+    Score: 50
+  - ID: 128047
+    Group: "AG_BATTLE"
+    Name: "Endless Tower challenger"
+    Target:
+      - MobID: 1956
+        Count: 1
+    Score: 10
+  - ID: 128048
+    Group: "AG_BATTLE"
+    Name: "Endless Tower Slayer"
+    Target:
+      - MobID: 1956
+        Count: 10
+    Score: 20
+  - ID: 128049
+    Group: "AG_BATTLE"
+    Name: "Lord of the tower"
+    Target:
+      - MobID: 1956
+        Count: 50
+    Score: 50
+  - ID: 128050
+    Group: "AG_BATTLE"
+    Name: "Novice Exorcist"
+    #Target:
+    #  - MobID: 2327
+    #    Count: 1
+    Score: 10
+  - ID: 128051
+    Group: "AG_BATTLE"
+    Name: "Experienced Exorcist"
+    #Target:
+    #  - MobID: 2327
+    #    Count: 10
+    Score: 20
+  - ID: 128052
+    Group: "AG_BATTLE"
+    Name: "Legendary Exorcist"
+    #Target:
+    #  - MobID: 2327
+    #    Count: 50
+    Score: 50
+  - ID: 129001
+    Group: "AG_ADVENTURE"
+    Name: "Prontera Explorer"
+    Dependent: [120001, 120002, 120003, 120004, 120005, 120006, 120007, 120008, 120009, 120010]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129002
+    Group: "AG_ADVENTURE"
+    Name: "Geffen Explorer"
+    Dependent: [120011, 120012, 120013, 120014, 120015, 120016, 120017]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129003
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Explorer"
+    Dependent: [120018, 120019, 120020, 120021, 120022, 120023]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129004
+    Group: "AG_ADVENTURE"
+    Name: "Payon Explorer"
+    Dependent: [120024, 120025, 120026, 120027, 120028, 120029, 120030, 120031]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129005
+    Group: "AG_ADVENTURE"
+    Name: "North Mjolnir Explorer"
+    Dependent: [120032, 120033, 120034, 120035, 120036]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129006
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Explorer"
+    Dependent: [120037, 120038, 120039, 120040, 120041, 120042, 120043]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129007
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Explorer"
+    Dependent: [120044, 120045, 120046, 120047, 120048, 120049, 120050, 120051]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129008
+    Group: "AG_ADVENTURE"
+    Name: "Rune Midgard Explorer"
+    Dependent: [129001, 129002, 129003, 129004, 129005, 129006, 129007]
+    Reward:
+      ItemID: 617
+    Score: 50
+  - ID: 129009
+    Group: "AG_ADVENTURE"
+    Name: "Yuno Explorer"
+    Dependent: [120052, 120053, 120054, 120055, 120056, 120057, 120058, 120059, 120060, 120061]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129010
+    Group: "AG_ADVENTURE"
+    Name: "Hugel Explorer"
+    Dependent: [120062, 120063, 120064, 120065, 120066]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129011
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Explorer"
+    Dependent: [120067, 120068, 120069, 120070, 120071, 120072, 120073, 120074]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129012
+    Group: "AG_ADVENTURE"
+    Name: "Lighthalzen Explorer"
+    Dependent: [120075, 120076, 120077]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129013
+    Group: "AG_ADVENTURE"
+    Name: "Schwarzwald Explorer"
+    Dependent: [129009, 129010, 129011, 129012]
+    Reward:
+      ItemID: 617
+    Score: 50
+  - ID: 129014
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Explorer"
+    Dependent: [120078, 120079, 120080, 120081, 120082, 120083, 120084]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129015
+    Group: "AG_ADVENTURE"
+    Name: "Veins Explorer"
+    Dependent: [120085, 120086, 120087, 120088, 120089]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129016
+    Group: "AG_ADVENTURE"
+    Name: "Arunafeltz Explorer"
+    Dependent: [129014, 129015]
+    Reward:
+      ItemID: 617
+    Score: 50
+  - ID: 129017
+    Group: "AG_ADVENTURE"
+    Name: "Laphine Explorer"
+    Dependent: [120090, 120091, 120092, 120093, 120094, 120095]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129018
+    Group: "AG_ADVENTURE"
+    Name: "Manuk Explorer"
+    Dependent: [120096, 120097, 120098, 120099, 120100]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129019
+    Group: "AG_ADVENTURE"
+    Name: "Eclage Explorer"
+    Dependent: [129017, 129018]
+    Reward:
+      ItemID: 617
+    Score: 50
+  - ID: 129020
+    Group: "AG_ADVENTURE"
+    Name: "Localizing fields explorer"
+    Dependent: [120101, 120102, 120103, 120104, 120105, 120106, 120107, 120108, 120109]
+    Reward:
+      ItemID: 617
+    Score: 50
+  - ID: 130000 # Talk to Prince NPC (npc/quests/quests_morocc.txt L5288)
+    Group: "AG_CHATTING"
+    Name: "Socialite debut"
+    Reward:
+      TitleID: 1034
+    Score: 10
+  - ID: 170000
+    Group: "AG_HEAR"
+    Name: "Song chamber is not an accident"
+    Score: 10
+  - ID: 190000
+    Group: "AG_CHATTING"
+    Name: "Alliance workers of merchant city"
+    Score: 50
+  - ID: 200000
+    Group: "AG_GOAL_LEVEL"
+    Name: "Acquire the first aura!"
+    Condition: " BaseLevel >= 99 "
+    Reward:
+      ItemID: 12549
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+      TitleID: 1000
+    Score: 50
+  - ID: 200001
+    Group: "AG_GOAL_LEVEL"
+    Name: "Acquire the second aura!"
+    Condition: " BaseLevel >= 150 "
+    Dependent: [200000]
+    Reward:
+      ItemID: 5364
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+      TitleID: 1001
+    Score: 60
+  - ID: 200002
+    Group: "AG_GOAL_LEVEL"
+    Name: "Acquire the third aura!"
+    Condition: " BaseLevel >= 175 "
+    Dependent: [200001]
+    Reward:
+    #  ItemID: 18880
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+      TitleID: 1002
+    Score: 70
+  - ID: 200003
+    Group: "AG_GOAL_LEVEL"
+    Name: "Master Job level!"
+    Condition: " JobLevel >= 50 "
+    Reward:
+      ItemID: 617
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+      TitleID: 1003
+    Score: 30
+  - ID: 200004
+    Group: "AG_GOAL_LEVEL"
+    Name: "Grandmaster Job level!"
+    Condition: " JobLevel >= 70 "
+    Dependent: [200003]
+    Reward:
+    #  ItemID: 12817
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+      TitleID: 1004
+    Score: 50
+  - ID: 200005
+    Group: "AG_JOB_CHANGE"
+    Name: "Official Adventurer"
+    Condition: " Class >= JOB_SWORDMAN && Class <= JOB_THIEF "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 200006
+    Group: "AG_JOB_CHANGE"
+    Name: "First step of job change!"
+    Condition: " Class >= JOB_SWORDMAN && Class <= JOB_THIEF "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 20
+  - ID: 200007
+    Group: "AG_JOB_CHANGE"
+    Name: "Veteran Adventurer! (1)"
+    Condition: " Class >= JOB_KNIGHT && Class <= JOB_ASSASSIN "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 25
+  - ID: 200008
+    Group: "AG_JOB_CHANGE"
+    Name: "Veteran Adventurer! (2)"
+    Condition: " Class >= JOB_CRUSADER && Class <= JOB_DANCER "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 25
+  - ID: 200009
+    Group: "AG_JOB_CHANGE"
+    Name: "Warrior (1)"
+    Condition: " Class >= JOB_LORD_KNIGHT && Class <= JOB_ASSASSIN_CROSS "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 30
+  - ID: 200010
+    Group: "AG_JOB_CHANGE"
+    Name: "Warrior (2)"
+    Condition: " Class >= JOB_PALADIN && Class <= JOB_GYPSY "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 30
+  - ID: 200011
+    Group: "AG_JOB_CHANGE"
+    Name: "Elite Adventurer! (1)"
+    Condition: " Class >= JOB_RUNE_KNIGHT && Class <= JOB_GUILLOTINE_CROSS "
+    Reward:
+    #  ItemID: 16483
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 50
+  - ID: 200012
+    Group: "AG_JOB_CHANGE"
+    Name: "Transcendentaler! (1)"
+    Condition: " Class >= JOB_RUNE_KNIGHT_T && Class <= JOB_GUILLOTINE_CROSS_T "
+    Reward:
+    #  ItemID: 16483
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 60
+  - ID: 200013
+    Group: "AG_JOB_CHANGE"
+    Name: "Elite Adventurer! (2)"
+    Condition: " Class >= JOB_ROYAL_GUARD && Class <= JOB_SHADOW_CHASER "
+    Reward:
+    #  ItemID: 16483
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 50
+  - ID: 200014
+    Group: "AG_JOB_CHANGE"
+    Name: "Transcendentaler! (2)"
+    Condition: " Class >= JOB_ROYAL_GUARD_T && Class <= JOB_SHADOW_CHASER_T "
+    Reward:
+    #  ItemID: 16483
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 60
+  - ID: 200015
+    Group: "AG_JOB_CHANGE"
+    Name: "The way of exceptional character"
+    Condition: " Class == JOB_SUPER_NOVICE || Class == JOB_GUNSLINGER || Class == JOB_NINJA || Class == JOB_TAEKWON "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 200016
+    Group: "AG_JOB_CHANGE"
+    Name: "This is My way!"
+    Condition: " Class == JOB_STAR_GLADIATOR || Class == JOB_SOUL_LINKER || Class == JOB_KAGEROU || Class == JOB_OBORO || Class == JOB_REBELLION "
+    Reward:
+    #  ItemID: 16483
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 20
+  - ID: 200017
+    Group: "AG_GOAL_STATUS"
+    Name: "Bearish Power!"
+    Condition: " bStr >= 90 "
+    Score: 10
+  - ID: 200018
+    Group: "AG_GOAL_STATUS"
+    Name: "Overflowing Magic!"
+    Condition: " bInt >= 90 "
+    Score: 10
+  - ID: 200019
+    Group: "AG_GOAL_STATUS"
+    Name: "Healthy Body and Mental Health!"
+    Condition: " bVit >= 90 "
+    Score: 10
+  - ID: 200020
+    Group: "AG_GOAL_STATUS"
+    Name: "Speed of Light"
+    Condition: " bAgi >= 90 "
+    Score: 10
+  - ID: 200021
+    Group: "AG_GOAL_STATUS"
+    Name: "Hawk Eyes"
+    Condition: " bDex >= 90 "
+    Score: 10
+  - ID: 200022
+    Group: "AG_GOAL_STATUS"
+    Name: "Maximum Luck"
+    Condition: " bLuk >= 90 "
+    Score: 10
+  - ID: 200023
+    Group: "AG_GOAL_STATUS"
+    Name: "Dragonlike Power!"
+    Condition: " bStr >= 125 "
+    Reward:
+      Script: " sc_start SC_GIANTGROWTH,180000,1; "
+    Score: 20
+  - ID: 200024
+    Group: "AG_GOAL_STATUS"
+    Name: "Magic Insanity"
+    Condition: " bInt >= 125 "
+    Reward:
+      Script: " specialeffect2 EF_HASTEUP; bonus_script \"{ bonus2 bHPLossRate,100,10000; bonus bBaseAtk,20; bonus bAspdRate,25; }\",60,0,0,SI_STEAMPACK; "
+    Score: 20
+  - ID: 200025
+    Group: "AG_GOAL_STATUS"
+    Name: "Rock Alloy"
+    Condition: " bVit >= 125 "
+    Reward:
+      Script: " specialeffect2 EF_HEAL3; sc_start2 SC_S_LIFEPOTION,600000,-5,5; "
+    Score: 20
+  - ID: 200026
+    Group: "AG_GOAL_STATUS"
+    Name: "Speed of Light"
+    Condition: " bAgi >= 125 "
+    Reward:
+      Script: " specialeffect2 EF_STEAL; sc_start SC_INCFLEE2,60000,20; "
+    Score: 20
+  - ID: 200027
+    Group: "AG_GOAL_STATUS"
+    Name: "Falcon's Eyes"
+    Condition: " bDex >= 125 "
+    Reward:
+      Script: " specialeffect2 EF_MAGICALATTHIT; sc_start SC_INCCRI,300000,30; "
+    Score: 20
+  - ID: 200028
+    Group: "AG_GOAL_STATUS"
+    Name: "Lucky Fever"
+    Condition: " bLuk >= 125 "
+    Reward:
+      Script: " specialeffect2 EF_GLORIA; sc_start SC_GLORIA,15000,0; "
+    Score: 20
+  - ID: 200029
+    Group: "AG_GOAL_STATUS"
+    Name: "Incarnation of Love and Hate"
+    Condition: " BaseLevel == 99 && Class == JOB_NOVICE "
+    Reward:
+    #  ItemID: 16483
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+    Score: 30
+  - ID: 200030
+    Group: "AG_GOAL_STATUS"
+    Name: "I really love it!"
+    Condition: " BaseLevel == 99 && (Class >= JOB_SWORDMAN && Class <= JOB_THIEF) "
+    Reward:
+    #  ItemID: 16504
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+    Score: 30
+  - ID: 200031
+    Group: "AG_JOB_CHANGE"
+    Name: "Reborn in Valhalla!"
+    Condition: " BaseLevel == 99 && Class == JOB_NOVICE_HIGH "
+    Reward:
+    #  ItemID: 22808
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 230100
+    Group: "AG_TAMING"
+    Name: "Poring is Love"
+    Dependent: [230101, 230102, 230103, 230104]
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+      TitleID: 1025
+    Score: 50
+  - ID: 230110
+    Group: "AG_TAMING"
+    Name: "Entomologist"
+    Dependent: [230111, 230112, 230113, 230114, 230115, 230116]
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+      TitleID: 1026
+    Score: 50
+  - ID: 230120
+    Group: "AG_TAMING"
+    Name: "Animals are also our friend"
+    Dependent: [230121, 230122, 230123, 230124, 230125, 230126, 230127, 230128]
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+      TitleID: 1027
+    Score: 50
+  - ID: 230140
+    Group: "AG_TAMING"
+    Name: "Monster Girls Unite!!"
+    Dependent: [230141, 230142, 230143, 230144, 230145, 230146, 230147]
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+      TitleID: 1029
+    Score: 50
+  - ID: 230101
+    Group: "AG_TAMING"
+    Name: "Poring - taming"
+    Target:
+      - MobID: 1002
+        Count: 1
+    Score: 10
+  - ID: 230102
+    Group: "AG_TAMING"
+    Name: "Drops - taming"
+    Target:
+      - MobID: 1113
+        Count: 1
+    Score: 10
+  - ID: 230103
+    Group: "AG_TAMING"
+    Name: "Poporing - taming"
+    Target:
+      - MobID: 1031
+        Count: 1
+    Score: 10
+  - ID: 230104
+    Group: "AG_TAMING"
+    Name: "Novice Poring - taming"
+    #Target:
+    #  - MobID: 2398
+    #    Count: 1
+    Score: 10
+  - ID: 230111
+    Group: "AG_TAMING"
+    Name: "Chonchon - taming"
+    Target:
+      - MobID: 1011
+        Count: 1
+    Score: 10
+  - ID: 230112
+    Group: "AG_TAMING"
+    Name: "Steel Chonchon - taming"
+    Target:
+      - MobID: 1042
+        Count: 1
+    Score: 10
+  - ID: 230113
+    Group: "AG_TAMING"
+    Name: "Hunter Fly - taming"
+    Target:
+      - MobID: 1035
+        Count: 1
+    Score: 10
+  - ID: 230114
+    Group: "AG_TAMING"
+    Name: "Rocker - taming"
+    Target:
+      - MobID: 1052
+        Count: 1
+    Score: 10
+  - ID: 230115
+    Group: "AG_TAMING"
+    Name: "Spore - taming"
+    Target:
+      - MobID: 1014
+        Count: 1
+    Score: 10
+  - ID: 230116
+    Group: "AG_TAMING"
+    Name: "Poison Spore - taming"
+    Target:
+      - MobID: 1077
+        Count: 1
+    Score: 10
+  - ID: 230121
+    Group: "AG_TAMING"
+    Name: "Lunatic - taming"
+    Target:
+      - MobID: 1063
+        Count: 1
+    Score: 10
+  - ID: 230122
+    Group: "AG_TAMING"
+    Name: "Picky - taming"
+    Target:
+      - MobID: 1049
+        Count: 1
+    Score: 10
+  - ID: 230123
+    Group: "AG_TAMING"
+    Name: "Savage Bebe - taming"
+    Target:
+      - MobID: 1167
+        Count: 1
+    Score: 10
+  - ID: 230124
+    Group: "AG_TAMING"
+    Name: "Baby Desert Wolf - taming"
+    Target:
+      - MobID: 1107
+        Count: 1
+    Score: 10
+  - ID: 230125
+    Group: "AG_TAMING"
+    Name: "Smokie - taming"
+    Target:
+      - MobID: 1056
+        Count: 1
+    Score: 10
+  - ID: 230126
+    Group: "AG_TAMING"
+    Name: "Yoyo - taming"
+    Target:
+      - MobID: 1057
+        Count: 1
+    Score: 10
+  - ID: 230127
+    Group: "AG_TAMING"
+    Name: "Peco Peco - taming"
+    Target:
+      - MobID: 1019
+        Count: 1
+    Score: 10
+  - ID: 230128
+    Group: "AG_TAMING"
+    Name: "Petite - taming"
+    Target:
+      - MobID: 1155
+        Count: 1
+    Score: 10
+  - ID: 230141
+    Group: "AG_TAMING"
+    Name: "Munak - taming"
+    Target:
+      - MobID: 1026
+        Count: 1
+    Score: 10
+  - ID: 230142
+    Group: "AG_TAMING"
+    Name: "Isis - taming"
+    Target:
+      - MobID: 1029
+        Count: 1
+    Score: 10
+  - ID: 230143
+    Group: "AG_TAMING"
+    Name: "Sohee - taming"
+    Target:
+      - MobID: 1170
+        Count: 1
+    Score: 10
+  - ID: 230144
+    Group: "AG_TAMING"
+    Name: "Zherlthsh - taming"
+    Target:
+      - MobID: 1200
+        Count: 1
+    Score: 10
+  - ID: 230145
+    Group: "AG_TAMING"
+    Name: "Alice - taming"
+    Target:
+      - MobID: 1275
+        Count: 1
+    Score: 10
+  - ID: 230146
+    Group: "AG_TAMING"
+    Name: "Succubus - taming"
+    Target:
+      - MobID: 1370
+        Count: 1
+    Score: 10
+  - ID: 230147
+    Group: "AG_TAMING"
+    Name: "Loli Ruri - taming"
+    Target:
+      - MobID: 1505
+        Count: 1
+    Score: 10
+  - ID: 220000
+    Group: "AG_CHATTING_CREATE"
+    Name: "Community begin"
+    Condition: " true "
+    Score: 10
+  - ID: 220001
+    Group: "AG_CHATTING_DYING"
+    Name: "A mouth only moment"
+    Condition: " true "
+    Score: 10
+  - ID: 220002
+    Group: "AG_CHATTING_COUNT"
+    Name: "Admiring the chatter"
+    Condition: " ARG0 == 20 "
+    Score: 10
+  - ID: 220003
+    Group: "AG_ADD_FRIEND"
+    Name: "My friend's friend~"
+    Condition: " ARG0 >= 1 "
+    Score: 10
+  - ID: 220004
+    Group: "AG_ADD_FRIEND"
+    Name: "A competition of popularity"
+    Condition: " ARG0 >= 10 "
+    Score: 10
+  - ID: 220005
+    Group: "AG_PARTY"
+    Name: "Let's Party~"
+    Condition: " true "
+    Score: 10
+  - ID: 220006
+    Group: "AG_MARRY"
+    Name: "Married with who..?"
+    Condition: " true "
+    Reward:
+      TitleID: 1022
+    Score: 20
+  - ID: 220007
+    Group: "AG_BABY"
+    Name: "Can you grow?"
+    Condition: " ARG0 == 1 "
+    Reward:
+      TitleID: 1032
+    Score: 20
+  - ID: 220008
+    Group: "AG_BABY"
+    Name: "Being a parent"
+    Condition: " ARG0 == 2 "
+    Reward:
+      TitleID: 1033
+    Score: 20
+  - ID: 220009
+    Group: "AG_SPEND_ZENY"
+    Name: "Activating the market economy (1)"
+    Condition: " ARG0 >= 10000 "
+    Target:
+      Count: 10000
+    Score: 10
+  - ID: 220010
+    Group: "AG_SPEND_ZENY"
+    Name: "Activating the market economy (2)"
+    Condition: " ARG0 >= 100000 "
+    Target:
+      Count: 100000
+    Score: 15
+  - ID: 220011
+    Group: "AG_SPEND_ZENY"
+    Name: "Activating the market economy (3)"
+    Condition: " ARG0 >= 500000 "
+    Target:
+      Count: 500000
+    Score: 20
+  - ID: 220012
+    Group: "AG_SPEND_ZENY"
+    Name: "Activating the market economy (4)"
+    Condition: " ARG0 >= 1000000 "
+    Target:
+      Count: 1000000
+    Score: 30
+  - ID: 220013
+    Group: "AG_SPEND_ZENY"
+    Name: "Activating the market economy (5)"
+    Condition: " ARG0 >= 5000000 "
+    Target:
+      Count: 5000000
+    Score: 50
+  - ID: 220014
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (1)"
+    Condition: " ARG0 == 1 && ARG1 >= 7 "
+    Score: 10
+  - ID: 220015
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (2)"
+    Condition: " ARG0 == 1 && ARG1 >= 12 "
+    Score: 15
+  - ID: 220016
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (3)"
+    Condition: " ARG0 == 2 && ARG1 >= 7 "
+    Score: 10
+  - ID: 220017
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (4)"
+    Condition: " ARG0 == 2 && ARG1 >= 12 "
+    Score: 15
+  - ID: 220018
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (5)"
+    Condition: " ARG0 == 3 && ARG1 >= 7 "
+    Score: 15
+  - ID: 220019
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (6)"
+    Condition: " ARG0 == 3 && ARG1 >= 12 "
+    Score: 20
+  - ID: 220020
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (7)"
+    Condition: " ARG0 == 4 && ARG1 >= 7 "
+    Score: 20
+  - ID: 220021
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (8)"
+    Condition: " ARG0 == 4 && ARG1 >= 12 "
+    Score: 30
+  - ID: 220022
+    Group: "AG_ENCHANT_FAIL"
+    Name: "Human's greed has no ending.."
+    Condition: " true "
+    Score: 10
+  - ID: 220023
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (1)"
+    Condition: " ARG0 >= 100 "
+    Score: 10
+  - ID: 220024
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (2)"
+    Condition: " ARG0 >= 1000 "
+    Score: 10
+  - ID: 220025
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (3)"
+    Condition: " ARG0 >= 5000 "
+    Score: 15
+  - ID: 220026
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (4)"
+    Condition: " ARG0 >= 10000 "
+    Score: 15
+  - ID: 220027
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (5)"
+    Condition: " ARG0 >= 50000 "
+    Score: 20
+  - ID: 220028
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (6)"
+    Condition: " ARG0 >= 100000 "
+    Score: 20
+  - ID: 220029
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (7)"
+    Condition: " ARG0 >= 150000 "
+    Score: 30
+  - ID: 220030
+    Group: "AG_GET_ZENY"
+    Name: "Rich King (1)"
+    Condition: " ARG0 >= 10000 "
+    Score: 10
+  - ID: 220031
+    Group: "AG_GET_ZENY"
+    Name: "Rich King (2)"
+    Condition: " ARG0 >= 100000 "
+    Score: 15
+  - ID: 220032
+    Group: "AG_GET_ZENY"
+    Name: "Rich King (3)"
+    Condition: " ARG0 >= 1000000 "
+    Score: 20
+  - ID: 220033
+    Group: "AG_GET_ZENY"
+    Name: "Rich King (4)"
+    Condition: " ARG0 >= 10000000 "
+    Score: 25
+  - ID: 220034
+    Group: "AG_GET_ZENY"
+    Name: "Rich King (5)"
+    Condition: " ARG0 >= 100000000 "
+    Score: 30
+  - ID: 220035
+    Group: "AG_GET_ZENY"
+    Name: "Rich King (6)"
+    Condition: " ARG0 >= 1000000000 "
+    Score: 40
+  - ID: 230200
+    Group: "AG_BATTLE"
+    Name: "Poring seeker"
+    Dependent: [230201, 230202, 230203]
+    Score: 10
+  - ID: 230201
+    Group: "AG_BATTLE"
+    Name: "Exploring Poring's life (1)"
+    Target:
+      - MobID: 1002
+        Count: 10
+    #  - MobID: 2398
+    #    Count: 10
+      - MobID: 1113
+        Count: 10
+      - MobID: 1031
+        Count: 10
+      - MobID: 1242
+        Count: 10
+    Score: 10
+  - ID: 230202
+    Group: "AG_BATTLE"
+    Name: "Exploring Poring's life (2)"
+    Target:
+      - MobID: 1090
+        Count: 1
+      - MobID: 1582
+        Count: 1
+      - MobID: 1096
+        Count: 1
+      - MobID: 1388
+        Count: 1
+      - MobID: 1120
+        Count: 1
+    Score: 15
+  - ID: 230203
+    Group: "AG_BATTLE"
+    Name: "Exploring Poring's life (3)"
+    Target:
+      - MobID: 1613
+        Count: 5
+      - MobID: 1977
+        Count: 5
+      - MobID: 1836
+        Count: 5
+    Score: 20
+  - ID: 240000
+    Group: "AG_GOAL_LEVEL"
+    Name: "Complete challenges after first introduction"
+    Score: 10
+  - ID: 240001
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 1"
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240002
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 2"
+    Dependent: [240001]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240003
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 3"
+    Dependent: [240002]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240004
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 4"
+    Dependent: [240003]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240005
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 5"
+    Dependent: [240004]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240006
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 6"
+    Dependent: [240005]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240007
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 7"
+    Dependent: [240006]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240008
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 8"
+    Dependent: [240007]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240009
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 9"
+    Dependent: [240008]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240010
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 10"
+    Dependent: [240009]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+      TitleID: 1023
+    Score: 10
+  - ID: 240011
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 11"
+    Dependent: [240010]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240012
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 12"
+    Dependent: [240011]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240013
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 13"
+    Dependent: [240012]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240014
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 14"
+    Dependent: [240013]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240015
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 15"
+    Dependent: [240014]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240016
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 16"
+    Dependent: [240015]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240017
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 17"
+    Dependent: [240016]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240018
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 18"
+    Dependent: [240017]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240019
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 19"
+    Dependent: [240018]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240020
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 20"
+    Dependent: [240019]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+      TitleID: 1024
+    Score: 10
+  - ID: 220036
+    Group: "AG_EAT"
+    Name: "The beginning of outdoor"
+    Score: 20
+  - ID: 220037
+    Group: "AG_EAT"
+    Name: "The first step becoming a chef"
+    Score: 20

+ 2407 - 0
db/re/achievement_db.yml

@@ -0,0 +1,2407 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2017 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 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/>.
+#
+###########################################################################
+# Custom Achievement Database
+###########################################################################
+#
+# Achievement Settings
+#
+###########################################################################
+# ID - Unique achievement ID.
+###########################################################################
+# Group - Achievement group type. Each achievement type calls a specific
+# objective check.
+# Valid groups:
+#  AG_ADD_FRIEND
+#  AG_ADVENTURE
+#  AG_BABY
+#  AG_BATTLE
+#  AG_CHATTING
+#  AG_CHATTING_COUNT
+#  AG_CHATTING_CREATE
+#  AG_CHATTING_DYING
+#  AG_EAT
+#  AG_GET_ITEM
+#  AG_GET_ZENY
+#  AG_GOAL_ACHIEVE
+#  AG_GOAL_LEVEL
+#  AG_GOAL_STATUS
+#  AG_HEAR
+#  AG_JOB_CHANGE
+#  AG_MARRY
+#  AG_PARTY
+#  AG_ENCHANT_FAIL
+#  AG_ENCHANT_SUCCESS
+#  AG_SEE
+#  AG_SPEND_ZENY
+#  AG_TAMING
+###########################################################################
+# Name - Achievement name. Used when sending rewards through RODEX.
+###########################################################################
+# Target - A list of monster ID and count values that the achievement
+# requires. The target count can also be used for achievements that keep
+# a counter while not being related to monster kills.
+# Capped at MAX_ACHIEVEMENT_OBJECTIVES.
+###########################################################################
+# Condition - A conditional statement that must be met for the achievement
+# to be considered complete.
+###########################################################################
+# Map - A map name that is used for the AG_CHATTING type which increments
+# the counter based on the player's map.
+###########################################################################
+# Dependent: - A list of achievement IDs that need to be completed before
+# this achievement is considered complete.
+###########################################################################
+# Reward - A list of rewards that are given on completion. All fields are
+# optional.
+#   ItemID: Item ID
+#   Amount:  Amount of Item ID (default 1)
+#   Script: Bonus Script
+#   TitleID: Title ID
+###########################################################################
+# Score - Achievement points that are given on completion.
+###########################################################################
+
+Achievements:
+  - ID: 110000
+    Group: "AG_EAT"
+    Name: "At this time I live to eat"
+    Score: 10
+  - ID: 110001
+    Group: "AG_SEE"
+    Name: "A fan of this polarity"
+    Score: 10
+  - ID: 120001
+    Group: "AG_ADVENTURE"
+    Name: "North Prontera Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120002
+    Group: "AG_ADVENTURE"
+    Name: "North Prontera Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120003
+    Group: "AG_ADVENTURE"
+    Name: "North Prontera Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120004
+    Group: "AG_ADVENTURE"
+    Name: "West Prontera Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120005
+    Group: "AG_ADVENTURE"
+    Name: "West Prontera Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120006
+    Group: "AG_ADVENTURE"
+    Name: "East Prontera Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120007
+    Group: "AG_ADVENTURE"
+    Name: "South Prontera Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120008
+    Group: "AG_ADVENTURE"
+    Name: "South Prontera Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120009
+    Group: "AG_ADVENTURE"
+    Name: "South Prontera Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120010
+    Group: "AG_ADVENTURE"
+    Name: "South Prontera Field Exploration(4)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120011
+    Group: "AG_ADVENTURE"
+    Name: "East Geffen Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120012
+    Group: "AG_ADVENTURE"
+    Name: "Southeast Geffen Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120013
+    Group: "AG_ADVENTURE"
+    Name: "Northwest Geffen Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120014
+    Group: "AG_ADVENTURE"
+    Name: "Northwest Geffen Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120015
+    Group: "AG_ADVENTURE"
+    Name: "Northwest Geffen Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120016
+    Group: "AG_ADVENTURE"
+    Name: "South Geffen Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120017
+    Group: "AG_ADVENTURE"
+    Name: "South Geffen Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120018
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120019
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120020
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120021
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Field Exploration(4)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120022
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Field Exploration(5)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120023
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Field Exploration(6)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120024
+    Group: "AG_ADVENTURE"
+    Name: "Southwest Payon Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120025
+    Group: "AG_ADVENTURE"
+    Name: "Southwest Payon Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120026
+    Group: "AG_ADVENTURE"
+    Name: "Southwest Payon Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120027
+    Group: "AG_ADVENTURE"
+    Name: "Southwest Payon Field Exploration(4)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120028
+    Group: "AG_ADVENTURE"
+    Name: "East Payon Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120029
+    Group: "AG_ADVENTURE"
+    Name: "East Payon Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120030
+    Group: "AG_ADVENTURE"
+    Name: "East Payon Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120031
+    Group: "AG_ADVENTURE"
+    Name: "East Payon Field Exploration(4)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120032
+    Group: "AG_ADVENTURE"
+    Name: "North Mjolnir Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120033
+    Group: "AG_ADVENTURE"
+    Name: "North Mjolnir Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120034
+    Group: "AG_ADVENTURE"
+    Name: "North Mjolnir Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120035
+    Group: "AG_ADVENTURE"
+    Name: "North Mjolnir Field Exploration(4)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120036
+    Group: "AG_ADVENTURE"
+    Name: "North Mjolnir Field Exploration(5)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120037
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120038
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120039
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120040
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Field Exploration(4)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120041
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Field Exploration(5)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120042
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Field Exploration(6)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120043
+    Group: "AG_ADVENTURE"
+    Name: "South Aldebaran Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120044
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120045
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120046
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120047
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(4)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120048
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(5)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120049
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(6)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120050
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(7)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120051
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Field Exploration(8)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120052
+    Group: "AG_ADVENTURE"
+    Name: "Border Checkpoint Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120053
+    Group: "AG_ADVENTURE"
+    Name: "Border Checkpoint Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120054
+    Group: "AG_ADVENTURE"
+    Name: "Kiel Hyre Mansion Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120055
+    Group: "AG_ADVENTURE"
+    Name: "El Mes Plateau Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120056
+    Group: "AG_ADVENTURE"
+    Name: "El Mes Plateau Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120057
+    Group: "AG_ADVENTURE"
+    Name: "El Mes Plateau Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120058
+    Group: "AG_ADVENTURE"
+    Name: "El Mes Gorge Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120059
+    Group: "AG_ADVENTURE"
+    Name: "Kiel Hyre Academy Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120060
+    Group: "AG_ADVENTURE"
+    Name: "Guard Camp Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120061
+    Group: "AG_ADVENTURE"
+    Name: "Yuno Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120062
+    Group: "AG_ADVENTURE"
+    Name: "Front of Thanatos Tower Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120063
+    Group: "AG_ADVENTURE"
+    Name: "Hugel Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120064
+    Group: "AG_ADVENTURE"
+    Name: "Hugel Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120065
+    Group: "AG_ADVENTURE"
+    Name: "Hugel Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120066
+    Group: "AG_ADVENTURE"
+    Name: "Abyss Lake Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120067
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120068
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120069
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120070
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(4)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120071
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(5)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120072
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(6)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120073
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(7)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120074
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Field Exploration(8)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120075
+    Group: "AG_ADVENTURE"
+    Name: "Lighthalzen Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120076
+    Group: "AG_ADVENTURE"
+    Name: "Lighthalzen Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120077
+    Group: "AG_ADVENTURE"
+    Name: "Lighthalzen Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120078
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Audhumbla Plains Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120079
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Plains Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120080
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Plains Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120081
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Plains Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120082
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Audhumbla Grassland Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120083
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Audhumbla Grassland Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120084
+    Group: "AG_ADVENTURE"
+    Name: "Portus Luna Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120085
+    Group: "AG_ADVENTURE"
+    Name: "Veins Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120086
+    Group: "AG_ADVENTURE"
+    Name: "Veins Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120087
+    Group: "AG_ADVENTURE"
+    Name: "Veins Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120088
+    Group: "AG_ADVENTURE"
+    Name: "Veins Field Exploration(4)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120089
+    Group: "AG_ADVENTURE"
+    Name: "Veins Field Exploration(5)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120090
+    Group: "AG_ADVENTURE"
+    Name: "Eclage Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120091
+    Group: "AG_ADVENTURE"
+    Name: "North Bitfrost Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120092
+    Group: "AG_ADVENTURE"
+    Name: "South Bitfrost Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120093
+    Group: "AG_ADVENTURE"
+    Name: "Splendide Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120094
+    Group: "AG_ADVENTURE"
+    Name: "Splendide Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120095
+    Group: "AG_ADVENTURE"
+    Name: "Splendide Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120096
+    Group: "AG_ADVENTURE"
+    Name: "Manuk Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120097
+    Group: "AG_ADVENTURE"
+    Name: "Manuk Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120098
+    Group: "AG_ADVENTURE"
+    Name: "Manuk Field Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120099
+    Group: "AG_ADVENTURE"
+    Name: "Outskirts of Kamidal Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120100
+    Group: "AG_ADVENTURE"
+    Name: "Outskirts of Kamidal Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120101
+    Group: "AG_ADVENTURE"
+    Name: "Amatsu Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120102
+    Group: "AG_ADVENTURE"
+    Name: "Kunlun Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120103
+    Group: "AG_ADVENTURE"
+    Name: "Gonryun Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120104
+    Group: "AG_ADVENTURE"
+    Name: "Ayothaya Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120105
+    Group: "AG_ADVENTURE"
+    Name: "Moscovia Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120106
+    Group: "AG_ADVENTURE"
+    Name: "Brasilis Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120107
+    Group: "AG_ADVENTURE"
+    Name: "Dewata Field Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120108
+    Group: "AG_ADVENTURE"
+    Name: "Malaya Field Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120109
+    Group: "AG_ADVENTURE"
+    Name: "Malaya Field Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 10
+  - ID: 120110
+    Group: "AG_ADVENTURE"
+    Name: "Abbey Underground Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120111
+    Group: "AG_ADVENTURE"
+    Name: "Abyss Lake Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120112
+    Group: "AG_ADVENTURE"
+    Name: "Clock Tower Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120113
+    Group: "AG_ADVENTURE"
+    Name: "Amatsu Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120114
+    Group: "AG_ADVENTURE"
+    Name: "Ant Hell Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120115
+    Group: "AG_ADVENTURE"
+    Name: "Ayothaya Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120116
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120117
+    Group: "AG_ADVENTURE"
+    Name: "Brasilis Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120118
+    Group: "AG_ADVENTURE"
+    Name: "Clock Tower Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120119
+    Group: "AG_ADVENTURE"
+    Name: "Istana Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120120
+    Group: "AG_ADVENTURE"
+    Name: "Scaraba Hole Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120121
+    Group: "AG_ADVENTURE"
+    Name: "Bitfrost Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120122
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120123
+    Group: "AG_ADVENTURE"
+    Name: "Geffen Underground Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120124
+    Group: "AG_ADVENTURE"
+    Name: "Glastheim Dungeon Exploration(1)"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120125
+    Group: "AG_ADVENTURE"
+    Name: "Glastheim Dungeon Exploration(2)"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120126
+    Group: "AG_ADVENTURE"
+    Name: "Glastheim Dungeon Exploration(3)"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120127
+    Group: "AG_ADVENTURE"
+    Name: "Glastheim Dungeon Exploration(4)"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120128
+    Group: "AG_ADVENTURE"
+    Name: "Kunlun Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120129
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120130
+    Group: "AG_ADVENTURE"
+    Name: "Sphinx Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120131
+    Group: "AG_ADVENTURE"
+    Name: "Izlude Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120132
+    Group: "AG_ADVENTURE"
+    Name: "Robot Factory Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120133
+    Group: "AG_ADVENTURE"
+    Name: "Bio Lab Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120134
+    Group: "AG_ADVENTURE"
+    Name: "Gonryun Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120135
+    Group: "AG_ADVENTURE"
+    Name: "Nogg Road Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120136
+    Group: "AG_ADVENTURE"
+    Name: "Coal Mine Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120137
+    Group: "AG_ADVENTURE"
+    Name: "Pyramid Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120138
+    Group: "AG_ADVENTURE"
+    Name: "Orc Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120139
+    Group: "AG_ADVENTURE"
+    Name: "Payon Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120140
+    Group: "AG_ADVENTURE"
+    Name: "Labyrinth Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120141
+    Group: "AG_ADVENTURE"
+    Name: "Undersea Tunnel Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120142
+    Group: "AG_ADVENTURE"
+    Name: "Thanatos Tower Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120143
+    Group: "AG_ADVENTURE"
+    Name: "Thor Volcano Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120144
+    Group: "AG_ADVENTURE"
+    Name: "Sunken Ship Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120145
+    Group: "AG_ADVENTURE"
+    Name: "Turtle Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 120146
+    Group: "AG_ADVENTURE"
+    Name: "Toy Factory Dungeon Exploration"
+    Reward:
+      ItemID: 22876
+    Score: 20
+  - ID: 127001
+    Group: "AG_CHATTING"
+    Name: "Prontera Contribution"
+    Map: "prontera"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127002
+    Group: "AG_CHATTING"
+    Name: "Geffen Contribution"
+    Map: "geffen"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127003
+    Group: "AG_CHATTING"
+    Name: "Morocc Contribution"
+    Map: "morocc"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127004
+    Group: "AG_CHATTING"
+    Name: "Payon Contribution"
+    Map: "payon"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127005
+    Group: "AG_CHATTING"
+    Name: "Yuno Contribution"
+    Map: "yuno"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127006
+    Group: "AG_CHATTING"
+    Name: "Lighthalzen Contribution"
+    Map: "lighthalzen"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127007
+    Group: "AG_CHATTING"
+    Name: "Einbroch Contribution"
+    Map: "einbroch"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127008
+    Group: "AG_CHATTING"
+    Name: "Rachel Contribution"
+    Map: "rachel"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 127009
+    Group: "AG_CHATTING"
+    Name: "Veins Contribution"
+    Map: "veins"
+    Target:
+      Count: 100000
+    Score: 10
+  - ID: 128000
+    Group: "AG_BATTLE"
+    Name: "Uninvited Guest"
+    Target:
+      - MobID: 2996
+        Count: 1
+    Score: 10
+  - ID: 128001
+    Group: "AG_BATTLE"
+    Name: "Strange Guest"
+    Target:
+      - MobID: 2996
+        Count: 10
+    Score: 10
+  - ID: 128002
+    Group: "AG_BATTLE"
+    Name: "Get along with map..."
+    Target:
+      - MobID: 2996
+        Count: 25
+    Score: 20
+  - ID: 128003
+    Group: "AG_BATTLE"
+    Name: "Welcomed Guest"
+    Target:
+      - MobID: 2996
+        Count: 50
+    Score: 30
+  - ID: 128004
+    Group: "AG_BATTLE"
+    Name: "Kimmy's best friend"
+    Target:
+      - MobID: 2996
+        Count: 100
+    Score: 50
+  - ID: 128005
+    Group: "AG_BATTLE"
+    Name: "Novice Angler"
+    Target:
+      - MobID: 2322
+        Count: 1
+    Score: 10
+  - ID: 128006
+    Group: "AG_BATTLE"
+    Name: "Juicy Hunter"
+    Target:
+      - MobID: 2322
+        Count: 10
+    Score: 20
+  - ID: 128007
+    Group: "AG_BATTLE"
+    Name: "Rhythm Master"
+    Target:
+      - MobID: 2322
+        Count: 50
+    Score: 50
+  - ID: 128008
+    Group: "AG_BATTLE"
+    Name: "Bold Adventurer"
+    Target:
+      - MobID: 1929
+        Count: 1
+    Score: 10
+  - ID: 128009
+    Group: "AG_BATTLE"
+    Name: "Baphomet Hatred"
+    Target:
+      - MobID: 1929
+        Count: 10
+    Score: 20
+  - ID: 128010
+    Group: "AG_BATTLE"
+    Name: "Goat's Nemesis"
+    Target:
+      - MobID: 1929
+        Count: 50
+    Score: 50
+  - ID: 128011
+    Group: "AG_BATTLE"
+    Name: "Ordinary Tourist"
+    #Target:
+    #  - MobID: 3029
+    #    Count: 1
+    Score: 10
+  - ID: 128012
+    Group: "AG_BATTLE"
+    Name: "Backcountry Expert"
+    #Target:
+    #  - MobID: 3029
+    #    Count: 10
+    Score: 20
+  - ID: 128013
+    Group: "AG_BATTLE"
+    Name: "Able to eat more like this"
+    #Target:
+    #  - MobID: 3029
+    #    Count: 50
+    Score: 50
+  - ID: 128014
+    Group: "AG_BATTLE"
+    Name: "Digest hard meat"
+    Target:
+      - MobID: 2319
+        Count: 1
+    Score: 10
+  - ID: 128015
+    Group: "AG_BATTLE"
+    Name: "Master of Escape"
+    Target:
+      - MobID: 2319
+        Count: 10
+    Score: 20
+  - ID: 128016
+    Group: "AG_BATTLE"
+    Name: "Immortal Hunter"
+    Target:
+      - MobID: 2319
+        Count: 50
+    Score: 50
+  - ID: 128017
+    Group: "AG_BATTLE"
+    Name: "Stood up and overcame despair"
+    #Target:
+    #  - MobID: 3097
+    #    Count: 1
+    Score: 10
+  - ID: 128018
+    Group: "AG_BATTLE"
+    Name: "Ember of Hope"
+    #Target:
+    #  - MobID: 3097
+    #    Count: 10
+    Score: 10
+  - ID: 128019
+    Group: "AG_BATTLE"
+    Name: "Pouring Aurora"
+    #Target:
+    #  - MobID: 3097
+    #    Count: 25
+    Score: 20
+  - ID: 128020
+    Group: "AG_BATTLE"
+    Name: "Who is desperate? I am hopeless!"
+    #Target:
+    #  - MobID: 3097
+    #    Count: 50
+    Score: 30
+  - ID: 128021
+    Group: "AG_BATTLE"
+    Name: "I know god will save the world"
+    #Target:
+    #  - MobID: 3097
+    #    Count: 100
+    Score: 50
+  - ID: 128022
+    Group: "AG_BATTLE"
+    Name: "There was mercy in Morocc army"
+    #Target:
+    #  - MobID: 3000
+    #  Count: 1
+    Score: 10
+  - ID: 128023
+    Group: "AG_BATTLE"
+    Name: "There was fear in Morocc army"
+    #Target:
+    #  - MobID: 3000
+    #    Count: 10
+    Score: 20
+  - ID: 128024
+    Group: "AG_BATTLE"
+    Name: "Guard of weak army"
+    #Target:
+    #  - MobID: 3000
+    #    Count: 50
+    Score: 50
+  - ID: 128025
+    Group: "AG_BATTLE"
+    Name: "Audience with the queen"
+    #Target:
+    #  - MobID: 2529
+    #    Count: 1
+    Score: 10
+  - ID: 128026
+    Group: "AG_BATTLE"
+    Name: "Warm earth"
+    #Target:
+    #  - MobID: 2533
+    #    Count: 1
+    Score: 10
+  - ID: 128027
+    Group: "AG_BATTLE"
+    Name: "Water is very good exactly"
+    #Target:
+    #  - MobID: 2534
+    #    Count: 1
+    Score: 10
+  - ID: 128028
+    Group: "AG_BATTLE"
+    Name: "Pleasant breeze"
+    #Target:
+    #  - MobID: 2535
+    #    Count: 1
+    Score: 10
+  - ID: 128029
+    Group: "AG_BATTLE"
+    Name: "Visitor of old castle"
+    Target:
+      - MobID: 2476
+        Count: 1
+    Score: 10
+  - ID: 128030
+    Group: "AG_BATTLE"
+    Name: "Lord of old castle"
+    Target:
+      - MobID: 2476
+        Count: 10
+    Score: 20
+  - ID: 128031
+    Group: "AG_BATTLE"
+    Name: "Conqueror of old castle"
+    Target:
+      - MobID: 2476
+        Count: 50
+    Score: 50
+  - ID: 128032
+    Group: "AG_BATTLE"
+    Name: "Haggard sucker"
+    #Target:
+    #  - MobID: 3150
+    #    Count: 1
+    Score: 10
+  - ID: 128033
+    Group: "AG_BATTLE"
+    Name: "Hope of the Knight"
+    #Target:
+    #  - MobID: 3150
+    #    Count: 10
+    Score: 20
+  - ID: 128034
+    Group: "AG_BATTLE"
+    Name: "Guardian of the Dawn"
+    #Target:
+    #  - MobID: 3150
+    #    Count: 50
+    Score: 50
+  - ID: 128035
+    Group: "AG_BATTLE"
+    Name: "Time Traveler"
+    #Target:
+    #  - MobID: 3190
+    #    Count: 1
+    Score: 10
+  - ID: 128036
+    Group: "AG_BATTLE"
+    Name: "Restore ancient relic"
+    #Target:
+    #  - MobID: 3190
+    #    Count: 10
+    Score: 20
+  - ID: 128037
+    Group: "AG_BATTLE"
+    Name: "Master of relic transport"
+    #Target:
+    #  - MobID: 3190
+    #    Count: 50
+    Score: 50
+  - ID: 128038
+    Group: "AG_BATTLE"
+    Name: "Show Jailbreak to the captain"
+    #Target:
+    #  - MobID: 3181
+    #    Count: 1
+    Score: 10
+  - ID: 128039
+    Group: "AG_BATTLE"
+    Name: "Show Jailbreak to the weak captain"
+    #Target:
+    #  - MobID: 3188
+    #    Count: 1
+    Score: 10
+  - ID: 128040
+    Group: "AG_BATTLE"
+    Name: "Riot on board"
+    #Target:
+    #  - MobID: 3181
+    #    Count: 1
+    Score: 20
+  - ID: 128041
+    Group: "AG_BATTLE"
+    Name: "Turmoil on board"
+    #Target:
+    #  - MobID: 3181
+    #    Count: 10
+    Score: 20
+  - ID: 128042
+    Group: "AG_BATTLE"
+    Name: "Rebellion on board"
+    #Target:
+    #  - MobID: 3181
+    #    Count: 50
+    Score: 50
+  - ID: 128043
+    Group: "AG_BATTLE"
+    Name: "Revolt of Riot"
+    #Target:
+    #  - MobID: 3188
+    #    Count: 50
+    Score: 50
+  - ID: 128044
+    Group: "AG_BATTLE"
+    Name: "Magic tournament champion"
+    Target:
+      - MobID: 2564
+        Count: 1
+    Score: 10
+  - ID: 128045
+    Group: "AG_BATTLE"
+    Name: "Gladiator of Coliseum"
+    Target:
+      - MobID: 2564
+        Count: 10
+    Score: 20
+  - ID: 128046
+    Group: "AG_BATTLE"
+    Name: "Slayer of Colosseum"
+    Target:
+      - MobID: 2564
+        Count: 50
+    Score: 50
+  - ID: 128047
+    Group: "AG_BATTLE"
+    Name: "Endless Tower challenger"
+    Target:
+      - MobID: 1956
+        Count: 1
+    Score: 10
+  - ID: 128048
+    Group: "AG_BATTLE"
+    Name: "Endless Tower Slayer"
+    Target:
+      - MobID: 1956
+        Count: 10
+    Score: 20
+  - ID: 128049
+    Group: "AG_BATTLE"
+    Name: "Lord of the tower"
+    Target:
+      - MobID: 1956
+        Count: 50
+    Score: 50
+  - ID: 128050
+    Group: "AG_BATTLE"
+    Name: "Novice Exorcist"
+    Target:
+      - MobID: 2327
+        Count: 1
+    Score: 10
+  - ID: 128051
+    Group: "AG_BATTLE"
+    Name: "Experienced Exorcist"
+    Target:
+      - MobID: 2327
+        Count: 10
+    Score: 20
+  - ID: 128052
+    Group: "AG_BATTLE"
+    Name: "Legendary Exorcist"
+    Target:
+      - MobID: 2327
+        Count: 50
+    Score: 50
+  - ID: 129001
+    Group: "AG_ADVENTURE"
+    Name: "Prontera Explorer"
+    Depdendent: [120001, 120002, 120003, 120004, 120005, 120006, 120007, 120008, 120009, 120010]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129002
+    Group: "AG_ADVENTURE"
+    Name: "Geffen Explorer"
+    Depdendent: [120011, 120012, 120013, 120014, 120015, 120016, 120017]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129003
+    Group: "AG_ADVENTURE"
+    Name: "Sograt Desert Explorer"
+    Depdendent: [120018, 120019, 120020, 120021, 120022, 120023]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129004
+    Group: "AG_ADVENTURE"
+    Name: "Payon Explorer"
+    Depdendent: [120024, 120025, 120026, 120027, 120028, 120029, 120030, 120031]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129005
+    Group: "AG_ADVENTURE"
+    Name: "North Mjolnir Explorer"
+    Depdendent: [120032, 120033, 120034, 120035, 120036]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129006
+    Group: "AG_ADVENTURE"
+    Name: "South Mjolnir Explorer"
+    Depdendent: [120037, 120038, 120039, 120040, 120041, 120042, 120043]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129007
+    Group: "AG_ADVENTURE"
+    Name: "Comodo Explorer"
+    Depdendent: [120044, 120045, 120046, 120047, 120048, 120049, 120050, 120051]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129008
+    Group: "AG_ADVENTURE"
+    Name: "Rune Midgard Explorer"
+    Depdendent: [129001, 129002, 129003, 129004, 129005, 129006, 129007]
+    Reward:
+      ItemID: 617
+    Score: 50
+  - ID: 129009
+    Group: "AG_ADVENTURE"
+    Name: "Yuno Explorer"
+    Depdendent: [120052, 120053, 120054, 120055, 120056, 120057, 120058, 120059, 120060, 120061]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129010
+    Group: "AG_ADVENTURE"
+    Name: "Hugel Explorer"
+    Depdendent: [120062, 120063, 120064, 120065, 120066]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129011
+    Group: "AG_ADVENTURE"
+    Name: "Einbroch Explorer"
+    Depdendent: [120067, 120068, 120069, 120070, 120071, 120072, 120073, 120074]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129012
+    Group: "AG_ADVENTURE"
+    Name: "Lighthalzen Explorer"
+    Depdendent: [120075, 120076, 120077]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129013
+    Group: "AG_ADVENTURE"
+    Name: "Schwarzwald Explorer"
+    Depdendent: [129009, 129010, 129011, 129012]
+    Reward:
+      ItemID: 617
+    Score: 50
+  - ID: 129014
+    Group: "AG_ADVENTURE"
+    Name: "Rachel Explorer"
+    Depdendent: [120078, 120079, 120080, 120081, 120082, 120083, 120084]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129015
+    Group: "AG_ADVENTURE"
+    Name: "Veins Explorer"
+    Depdendent: [120085, 120086, 120087, 120088, 120089]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129016
+    Group: "AG_ADVENTURE"
+    Name: "Arunafeltz Explorer"
+    Depdendent: [129014, 129015]
+    Reward:
+      ItemID: 617
+    Score: 50
+  - ID: 129017
+    Group: "AG_ADVENTURE"
+    Name: "Laphine Explorer"
+    Depdendent: [120090, 120091, 120092, 120093, 120094, 120095]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129018
+    Group: "AG_ADVENTURE"
+    Name: "Manuk Explorer"
+    Depdendent: [120096, 120097, 120098, 120099, 120100]
+    Reward:
+      ItemID: 644
+    Score: 20
+  - ID: 129019
+    Group: "AG_ADVENTURE"
+    Name: "Eclage Explorer"
+    Depdendent: [129017, 129018]
+    Reward:
+      ItemID: 617
+    Score: 50
+  - ID: 129020
+    Group: "AG_ADVENTURE"
+    Name: "Localizing fields explorer"
+    Depdendent: [120101, 120102, 120103, 120104, 120105, 120106, 120107, 120108, 120109]
+    Reward:
+      ItemID: 617
+    Score: 50
+  - ID: 130000 # Talk to Prince NPC (npc/quests/quests_morocc.txt L5288)
+    Group: "AG_CHATTING"
+    Name: "Socialite debut"
+    Reward:
+      TitleID: 1034
+    Score: 10
+  - ID: 170000
+    Group: "AG_HEAR"
+    Name: "Song chamber is not an accident"
+    Score: 10
+  - ID: 190000
+    Group: "AG_CHATTING"
+    Name: "Alliance workers of merchant city"
+    Score: 50
+  - ID: 200000
+    Group: "AG_GOAL_LEVEL"
+    Name: "Acquire the first aura!"
+    Condition: " BaseLevel >= 99 "
+    Reward:
+      ItemID: 12549
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+      TitleID: 1000
+    Score: 50
+  - ID: 200001
+    Group: "AG_GOAL_LEVEL"
+    Name: "Acquire the second aura!"
+    Condition: " BaseLevel >= 150 "
+    Depdendent: [200000]
+    Reward:
+      ItemID: 5364
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+      TitleID: 1001
+    Score: 60
+  - ID: 200002
+    Group: "AG_GOAL_LEVEL"
+    Name: "Acquire the third aura!"
+    Condition: " BaseLevel >= 175 "
+    Depdendent: [200001]
+    Reward:
+      ItemID: 18880
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+      TitleID: 1002
+    Score: 70
+  - ID: 200003
+    Group: "AG_GOAL_LEVEL"
+    Name: "Master Job level!"
+    Condition: " JobLevel >= 50 "
+    Reward:
+      ItemID: 617
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+      TitleID: 1003
+    Score: 30
+  - ID: 200004
+    Group: "AG_GOAL_LEVEL"
+    Name: "Grandmaster Job level!"
+    Condition: " JobLevel >= 70 "
+    Depdendent: [200003]
+    Reward:
+      ItemID: 12817
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+      TitleID: 1004
+    Score: 50
+  - ID: 200005
+    Group: "AG_JOB_CHANGE"
+    Name: "Official Adventurer"
+    Condition: " Class >= JOB_SWORDMAN && Class <= JOB_THIEF "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 200006
+    Group: "AG_JOB_CHANGE"
+    Name: "First step of job change!"
+    Condition: " Class >= JOB_SWORDMAN && Class <= JOB_THIEF "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 20
+  - ID: 200007
+    Group: "AG_JOB_CHANGE"
+    Name: "Veteran Adventurer! (1)"
+    Condition: " Class >= JOB_KNIGHT && Class <= JOB_ASSASSIN "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 25
+  - ID: 200008
+    Group: "AG_JOB_CHANGE"
+    Name: "Veteran Adventurer! (2)"
+    Condition: " Class >= JOB_CRUSADER && Class <= JOB_DANCER "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 25
+  - ID: 200009
+    Group: "AG_JOB_CHANGE"
+    Name: "Warrior (1)"
+    Condition: " Class >= JOB_LORD_KNIGHT && Class <= JOB_ASSASSIN_CROSS "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 30
+  - ID: 200010
+    Group: "AG_JOB_CHANGE"
+    Name: "Warrior (2)"
+    Condition: " Class >= JOB_PALADIN && Class <= JOB_GYPSY "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 30
+  - ID: 200011
+    Group: "AG_JOB_CHANGE"
+    Name: "Elite Adventurer! (1)"
+    Condition: " Class >= JOB_RUNE_KNIGHT && Class <= JOB_GUILLOTINE_CROSS "
+    Reward:
+      ItemID: 16483
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 50
+  - ID: 200012
+    Group: "AG_JOB_CHANGE"
+    Name: "Transcendentaler! (1)"
+    Condition: " Class >= JOB_RUNE_KNIGHT_T && Class <= JOB_GUILLOTINE_CROSS_T "
+    Reward:
+      ItemID: 16483
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 60
+  - ID: 200013
+    Group: "AG_JOB_CHANGE"
+    Name: "Elite Adventurer! (2)"
+    Condition: " Class >= JOB_ROYAL_GUARD && Class <= JOB_SHADOW_CHASER "
+    Reward:
+      ItemID: 16483
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 50
+  - ID: 200014
+    Group: "AG_JOB_CHANGE"
+    Name: "Transcendentaler! (2)"
+    Condition: " Class >= JOB_ROYAL_GUARD_T && Class <= JOB_SHADOW_CHASER_T "
+    Reward:
+      ItemID: 16483
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 60
+  - ID: 200015
+    Group: "AG_JOB_CHANGE"
+    Name: "The way of exceptional character"
+    Condition: " Class == JOB_SUPER_NOVICE || Class == JOB_GUNSLINGER || Class == JOB_NINJA || Class == JOB_TAEKWON "
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 200016
+    Group: "AG_JOB_CHANGE"
+    Name: "This is My way!"
+    Condition: " Class == JOB_STAR_GLADIATOR || Class == JOB_SOUL_LINKER || Class == JOB_KAGEROU || Class == JOB_OBORO || Class == JOB_REBELLION "
+    Reward:
+      ItemID: 16483
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 20
+  - ID: 200017
+    Group: "AG_GOAL_STATUS"
+    Name: "Bearish Power!"
+    Condition: " bStr >= 90 "
+    Score: 10
+  - ID: 200018
+    Group: "AG_GOAL_STATUS"
+    Name: "Overflowing Magic!"
+    Condition: " bInt >= 90 "
+    Score: 10
+  - ID: 200019
+    Group: "AG_GOAL_STATUS"
+    Name: "Healthy Body and Mental Health!"
+    Condition: " bVit >= 90 "
+    Score: 10
+  - ID: 200020
+    Group: "AG_GOAL_STATUS"
+    Name: "Speed of Light"
+    Condition: " bAgi >= 90 "
+    Score: 10
+  - ID: 200021
+    Group: "AG_GOAL_STATUS"
+    Name: "Hawk Eyes"
+    Condition: " bDex >= 90 "
+    Score: 10
+  - ID: 200022
+    Group: "AG_GOAL_STATUS"
+    Name: "Maximum Luck"
+    Condition: " bLuk >= 90 "
+    Score: 10
+  - ID: 200023
+    Group: "AG_GOAL_STATUS"
+    Name: "Dragonlike Power!"
+    Condition: " bStr >= 125 "
+    Reward:
+      Script: " sc_start SC_GIANTGROWTH,180000,1; "
+    Score: 20
+  - ID: 200024
+    Group: "AG_GOAL_STATUS"
+    Name: "Magic Insanity"
+    Condition: " bInt >= 125 "
+    Reward:
+      Script: " specialeffect2 EF_HASTEUP; bonus_script \"{ bonus2 bHPLossRate,100,10000; bonus bBaseAtk,20; bonus bAspdRate,25; }\",60,0,0,SI_STEAMPACK; "
+    Score: 20
+  - ID: 200025
+    Group: "AG_GOAL_STATUS"
+    Name: "Rock Alloy"
+    Condition: " bVit >= 125 "
+    Reward:
+      Script: " specialeffect2 EF_HEAL3; sc_start2 SC_S_LIFEPOTION,600000,-5,5; "
+    Score: 20
+  - ID: 200026
+    Group: "AG_GOAL_STATUS"
+    Name: "Speed of Light"
+    Condition: " bAgi >= 125 "
+    Reward:
+      Script: " specialeffect2 EF_STEAL; sc_start SC_INCFLEE2,60000,20; "
+    Score: 20
+  - ID: 200027
+    Group: "AG_GOAL_STATUS"
+    Name: "Falcon's Eyes"
+    Condition: " bDex >= 125 "
+    Reward:
+      Script: " specialeffect2 EF_MAGICALATTHIT; sc_start SC_INCCRI,300000,30; "
+    Score: 20
+  - ID: 200028
+    Group: "AG_GOAL_STATUS"
+    Name: "Lucky Fever"
+    Condition: " bLuk >= 125 "
+    Reward:
+      Script: " specialeffect2 EF_GLORIA; sc_start SC_GLORIA,15000,0; "
+    Score: 20
+  - ID: 200029
+    Group: "AG_GOAL_STATUS"
+    Name: "Incarnation of Love and Hate"
+    Condition: " BaseLevel == 99 && Class == JOB_NOVICE "
+    Reward:
+      ItemID: 16483
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+    Score: 30
+  - ID: 200030
+    Group: "AG_GOAL_STATUS"
+    Name: "I really love it!"
+    Condition: " BaseLevel == 99 && (Class >= JOB_SWORDMAN && Class <= JOB_THIEF) "
+    Reward:
+      ItemID: 16504
+      Script: " specialeffect2 EF_BLESSING; sc_start SC_BLESSING,30000,10; "
+    Score: 30
+  - ID: 200031
+    Group: "AG_JOB_CHANGE"
+    Name: "Reborn in Valhalla!"
+    Condition: " BaseLevel == 99 && Class == JOB_NOVICE_HIGH "
+    Reward:
+      ItemID: 22808
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 230100
+    Group: "AG_TAMING"
+    Name: "Poring is Love"
+    Depdendent: [230101, 230102, 230103, 230104]
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+      TitleID: 1025
+    Score: 50
+  - ID: 230110
+    Group: "AG_TAMING"
+    Name: "Entomologist"
+    Depdendent: [230111, 230112, 230113, 230114, 230115, 230116]
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+      TitleID: 1026
+    Score: 50
+  - ID: 230120
+    Group: "AG_TAMING"
+    Name: "Animals are also our friend"
+    Depdendent: [230121, 230122, 230123, 230124, 230125, 230126, 230127, 230128]
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+      TitleID: 1027
+    Score: 50
+  - ID: 230140
+    Group: "AG_TAMING"
+    Name: "Monster Girls Unite!!"
+    Depdendent: [230141, 230142, 230143, 230144, 230145, 230146, 230147]
+    Reward:
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+      TitleID: 1029
+    Score: 50
+  - ID: 230101
+    Group: "AG_TAMING"
+    Name: "Poring - taming"
+    Target:
+      - MobID: 1002
+        Count: 1
+    Score: 10
+  - ID: 230102
+    Group: "AG_TAMING"
+    Name: "Drops - taming"
+    Target:
+      - MobID: 1113
+        Count: 1
+    Score: 10
+  - ID: 230103
+    Group: "AG_TAMING"
+    Name: "Poporing - taming"
+    Target:
+      - MobID: 1031
+        Count: 1
+    Score: 10
+  - ID: 230104
+    Group: "AG_TAMING"
+    Name: "Novice Poring - taming"
+    Target:
+      - MobID: 2398
+        Count: 1
+    Score: 10
+  - ID: 230111
+    Group: "AG_TAMING"
+    Name: "Chonchon - taming"
+    Target:
+      - MobID: 1011
+        Count: 1
+    Score: 10
+  - ID: 230112
+    Group: "AG_TAMING"
+    Name: "Steel Chonchon - taming"
+    Target:
+      - MobID: 1042
+        Count: 1
+    Score: 10
+  - ID: 230113
+    Group: "AG_TAMING"
+    Name: "Hunter Fly - taming"
+    Target:
+      - MobID: 1035
+        Count: 1
+    Score: 10
+  - ID: 230114
+    Group: "AG_TAMING"
+    Name: "Rocker - taming"
+    Target:
+      - MobID: 1052
+        Count: 1
+    Score: 10
+  - ID: 230115
+    Group: "AG_TAMING"
+    Name: "Spore - taming"
+    Target:
+      - MobID: 1014
+        Count: 1
+    Score: 10
+  - ID: 230116
+    Group: "AG_TAMING"
+    Name: "Poison Spore - taming"
+    Target:
+      - MobID: 1077
+        Count: 1
+    Score: 10
+  - ID: 230121
+    Group: "AG_TAMING"
+    Name: "Lunatic - taming"
+    Target:
+      - MobID: 1063
+        Count: 1
+    Score: 10
+  - ID: 230122
+    Group: "AG_TAMING"
+    Name: "Picky - taming"
+    Target:
+      - MobID: 1049
+        Count: 1
+    Score: 10
+  - ID: 230123
+    Group: "AG_TAMING"
+    Name: "Savage Bebe - taming"
+    Target:
+      - MobID: 1167
+        Count: 1
+    Score: 10
+  - ID: 230124
+    Group: "AG_TAMING"
+    Name: "Baby Desert Wolf - taming"
+    Target:
+      - MobID: 1107
+        Count: 1
+    Score: 10
+  - ID: 230125
+    Group: "AG_TAMING"
+    Name: "Smokie - taming"
+    Target:
+      - MobID: 1056
+        Count: 1
+    Score: 10
+  - ID: 230126
+    Group: "AG_TAMING"
+    Name: "Yoyo - taming"
+    Target:
+      - MobID: 1057
+        Count: 1
+    Score: 10
+  - ID: 230127
+    Group: "AG_TAMING"
+    Name: "Peco Peco - taming"
+    Target:
+      - MobID: 1019
+        Count: 1
+    Score: 10
+  - ID: 230128
+    Group: "AG_TAMING"
+    Name: "Petite - taming"
+    Target:
+      - MobID: 1155
+        Count: 1
+    Score: 10
+  - ID: 230141
+    Group: "AG_TAMING"
+    Name: "Munak - taming"
+    Target:
+      - MobID: 1026
+        Count: 1
+    Score: 10
+  - ID: 230142
+    Group: "AG_TAMING"
+    Name: "Isis - taming"
+    Target:
+      - MobID: 1029
+        Count: 1
+    Score: 10
+  - ID: 230143
+    Group: "AG_TAMING"
+    Name: "Sohee - taming"
+    Target:
+      - MobID: 1170
+        Count: 1
+    Score: 10
+  - ID: 230144
+    Group: "AG_TAMING"
+    Name: "Zherlthsh - taming"
+    Target:
+      - MobID: 1200
+        Count: 1
+    Score: 10
+  - ID: 230145
+    Group: "AG_TAMING"
+    Name: "Alice - taming"
+    Target:
+      - MobID: 1275
+        Count: 1
+    Score: 10
+  - ID: 230146
+    Group: "AG_TAMING"
+    Name: "Succubus - taming"
+    Target:
+      - MobID: 1370
+        Count: 1
+    Score: 10
+  - ID: 230147
+    Group: "AG_TAMING"
+    Name: "Loli Ruri - taming"
+    Target:
+      - MobID: 1505
+        Count: 1
+    Score: 10
+  - ID: 220000
+    Group: "AG_CHATTING_CREATE"
+    Name: "Community begin"
+    Condition: " true "
+    Score: 10
+  - ID: 220001
+    Group: "AG_CHATTING_DYING"
+    Name: "A mouth only moment"
+    Condition: " true "
+    Score: 10
+  - ID: 220002
+    Group: "AG_CHATTING_COUNT"
+    Name: "Admiring the chatter"
+    Condition: " ARG0 == 20 "
+    Score: 10
+  - ID: 220003
+    Group: "AG_ADD_FRIEND"
+    Name: "My friend's friend~"
+    Condition: " ARG0 >= 1 "
+    Score: 10
+  - ID: 220004
+    Group: "AG_ADD_FRIEND"
+    Name: "A competition of popularity"
+    Condition: " ARG0 >= 10 "
+    Score: 10
+  - ID: 220005
+    Group: "AG_PARTY"
+    Name: "Let's Party~"
+    Condition: " true "
+    Score: 10
+  - ID: 220006
+    Group: "AG_MARRY"
+    Name: "Married with who..?"
+    Condition: " true "
+    Reward:
+      TitleID: 1022
+    Score: 20
+  - ID: 220007
+    Group: "AG_BABY"
+    Name: "Can you grow?"
+    Condition: " ARG0 == 1 "
+    Reward:
+      TitleID: 1032
+    Score: 20
+  - ID: 220008
+    Group: "AG_BABY"
+    Name: "Being a parent"
+    Condition: " ARG0 == 2 "
+    Reward:
+      TitleID: 1033
+    Score: 20
+  - ID: 220009
+    Group: "AG_SPEND_ZENY"
+    Name: "Activating the market economy (1)"
+    Condition: " ARG0 >= 10000 "
+    Target:
+      Count: 10000
+    Score: 10
+  - ID: 220010
+    Group: "AG_SPEND_ZENY"
+    Name: "Activating the market economy (2)"
+    Condition: " ARG0 >= 100000 "
+    Target:
+      Count: 100000
+    Score: 15
+  - ID: 220011
+    Group: "AG_SPEND_ZENY"
+    Name: "Activating the market economy (3)"
+    Condition: " ARG0 >= 500000 "
+    Target:
+      Count: 500000
+    Score: 20
+  - ID: 220012
+    Group: "AG_SPEND_ZENY"
+    Name: "Activating the market economy (4)"
+    Condition: " ARG0 >= 1000000 "
+    Target:
+      Count: 1000000
+    Score: 30
+  - ID: 220013
+    Group: "AG_SPEND_ZENY"
+    Name: "Activating the market economy (5)"
+    Condition: " ARG0 >= 5000000 "
+    Target:
+      Count: 5000000
+    Score: 50
+  - ID: 220014
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (1)"
+    Condition: " ARG0 == 1 && ARG1 >= 7 "
+    Score: 10
+  - ID: 220015
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (2)"
+    Condition: " ARG0 == 1 && ARG1 >= 12 "
+    Score: 15
+  - ID: 220016
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (3)"
+    Condition: " ARG0 == 2 && ARG1 >= 7 "
+    Score: 10
+  - ID: 220017
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (4)"
+    Condition: " ARG0 == 2 && ARG1 >= 12 "
+    Score: 15
+  - ID: 220018
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (5)"
+    Condition: " ARG0 == 3 && ARG1 >= 7 "
+    Score: 15
+  - ID: 220019
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (6)"
+    Condition: " ARG0 == 3 && ARG1 >= 12 "
+    Score: 20
+  - ID: 220020
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (7)"
+    Condition: " ARG0 == 4 && ARG1 >= 7 "
+    Score: 20
+  - ID: 220021
+    Group: "AG_ENCHANT_SUCCESS"
+    Name: "I can't quit from refining! (8)"
+    Condition: " ARG0 == 4 && ARG1 >= 12 "
+    Score: 30
+  - ID: 220022
+    Group: "AG_ENCHANT_FAIL"
+    Name: "Human's greed has no ending.."
+    Condition: " true "
+    Score: 10
+  - ID: 220023
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (1)"
+    Condition: " ARG0 >= 100 "
+    Score: 10
+  - ID: 220024
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (2)"
+    Condition: " ARG0 >= 1000 "
+    Score: 10
+  - ID: 220025
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (3)"
+    Condition: " ARG0 >= 5000 "
+    Score: 15
+  - ID: 220026
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (4)"
+    Condition: " ARG0 >= 10000 "
+    Score: 15
+  - ID: 220027
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (5)"
+    Condition: " ARG0 >= 50000 "
+    Score: 20
+  - ID: 220028
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (6)"
+    Condition: " ARG0 >= 100000 "
+    Score: 20
+  - ID: 220029
+    Group: "AG_GET_ITEM"
+    Name: "I found it! (7)"
+    Condition: " ARG0 >= 150000 "
+    Score: 30
+  - ID: 220030
+    Group: "AG_GET_ZENY"
+    Name: "Rich King (1)"
+    Condition: " ARG0 >= 10000 "
+    Score: 10
+  - ID: 220031
+    Group: "AG_GET_ZENY"
+    Name: "Rich King (2)"
+    Condition: " ARG0 >= 100000 "
+    Score: 15
+  - ID: 220032
+    Group: "AG_GET_ZENY"
+    Name: "Rich King (3)"
+    Condition: " ARG0 >= 1000000 "
+    Score: 20
+  - ID: 220033
+    Group: "AG_GET_ZENY"
+    Name: "Rich King (4)"
+    Condition: " ARG0 >= 10000000 "
+    Score: 25
+  - ID: 220034
+    Group: "AG_GET_ZENY"
+    Name: "Rich King (5)"
+    Condition: " ARG0 >= 100000000 "
+    Score: 30
+  - ID: 220035
+    Group: "AG_GET_ZENY"
+    Name: "Rich King (6)"
+    Condition: " ARG0 >= 1000000000 "
+    Score: 40
+  - ID: 230200
+    Group: "AG_BATTLE"
+    Name: "Poring seeker"
+    Depdendent: [230201, 230202, 230203]
+    Score: 10
+  - ID: 230201
+    Group: "AG_BATTLE"
+    Name: "Exploring Poring's life (1)"
+    Target:
+      - MobID: 1002
+        Count: 10
+      - MobID: 2398
+        Count: 10
+      - MobID: 1113
+        Count: 10
+      - MobID: 1031
+        Count: 10
+      - MobID: 1242
+        Count: 10
+    Score: 10
+  - ID: 230202
+    Group: "AG_BATTLE"
+    Name: "Exploring Poring's life (2)"
+    Target:
+      - MobID: 1090
+        Count: 1
+      - MobID: 1582
+        Count: 1
+      - MobID: 1096
+        Count: 1
+      - MobID: 1388
+        Count: 1
+      - MobID: 1120
+        Count: 1
+    Score: 15
+  - ID: 230203
+    Group: "AG_BATTLE"
+    Name: "Exploring Poring's life (3)"
+    Target:
+      - MobID: 1613
+        Count: 5
+      - MobID: 1977
+        Count: 5
+      - MobID: 1836
+        Count: 5
+    Score: 20
+  - ID: 240000
+    Group: "AG_GOAL_LEVEL"
+    Name: "Complete challenges after first introduction"
+    Score: 10
+  - ID: 240001
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 1"
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240002
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 2"
+    Depdendent: [240001]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240003
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 3"
+    Depdendent: [240002]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240004
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 4"
+    Depdendent: [240003]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240005
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 5"
+    Depdendent: [240004]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240006
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 6"
+    Depdendent: [240005]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240007
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 7"
+    Depdendent: [240006]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240008
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 8"
+    Depdendent: [240007]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240009
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 9"
+    Depdendent: [240008]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240010
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 10"
+    Depdendent: [240009]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+      TitleID: 1023
+    Score: 10
+  - ID: 240011
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 11"
+    Depdendent: [240010]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240012
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 12"
+    Depdendent: [240011]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240013
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 13"
+    Depdendent: [240012]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240014
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 14"
+    Depdendent: [240013]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240015
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 15"
+    Depdendent: [240014]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240016
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 16"
+    Depdendent: [240015]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240017
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 17"
+    Depdendent: [240016]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240018
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 18"
+    Depdendent: [240017]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240019
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 19"
+    Depdendent: [240018]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+    Score: 10
+  - ID: 240020
+    Group: "AG_GOAL_ACHIEVE"
+    Name: "Reaching Level 20"
+    Depdendent: [240019]
+    Reward:
+      ItemID: 644
+      Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
+      TitleID: 1024
+    Score: 10
+  - ID: 220036
+    Group: "AG_EAT"
+    Name: "The beginning of outdoor"
+    Score: 20
+  - ID: 220037
+    Group: "AG_EAT"
+    Name: "The first step becoming a chef"
+    Score: 20

+ 9 - 9
db/re/item_db.txt

@@ -1379,7 +1379,7 @@
 2174,Lumiere_Shield,Lumiere Shield,4,20,,1300,,50,,1,0xFFFFFFFF,63,2,32,,65,1,3,{},{},{}
 2175,Esprit_Shield,Spirit Shield,4,20,,1300,,50,,1,0xFFFFFFFF,63,2,32,,65,1,3,{},{},{}
 2176,Dark_Book,Black Book,4,20,,500,,80,,1,0xFFFFFFFF,63,2,32,,65,1,5,{ bonus bMdef,5; .@r = getrefine(); bonus3 bAutoSpellWhenHit,"NPC_DRAGONFEAR",1,(.@r<=6)?(10):((.@r<=8)?(20):(30)); },{},{}
-2177,Shield_Of_Death,Shield Of Death,4,20,,2000,,150,,1,0xFFFFFFFF,63,2,32,,90,1,3,{ bonus2 bAddClass,Class_Boss,2; bonus2 bMagicAddClass,Class_Boss,2; bonus2 bAddClass,Class_Normal,10; bonus2 bMagicAddClass,Class_Normal,10; },{},{}
+2177,Shield_Of_Death,Shield Of Death,4,20,,2000,,150,,1,0xFFFFFFFF,63,2,32,,90,1,3,{ bonus2 bAddClass,Class_Boss,2; bonus2 bMagicAddClass,Class_Boss,2; bonus2 bSubClass,Class_Normal,-10; },{},{}
 2178,TE_Woe_Buckler,TE Woe Buckler,4,0,,0,,15,,0,0xFFFFFFFF,63,2,32,1,40,1,2,{ bonus bMdef,15; bonus bMaxHP,100; bonus bMaxSP,100; bonus2 bSubRace,RC_Player,15; },{},{}
 2179,TE_Woe_Shield,TE Woe Shield,4,0,,0,,25,,0,0x000444A2,63,2,32,1,40,1,3,{ bonus bMdef,5; bonus bMaxHP,200; bonus2 bSubRace,RC_Player,20; },{},{}
 2180,TE_Woe_Magic_Guard,TE Woe Magic Guard,4,0,,0,,5,,0,0x00818315,63,2,32,1,40,1,1,{ bonus bMdef,25; bonus bMaxSP,200; bonus2 bSubRace,RC_Player,10; },{},{}
@@ -7296,8 +7296,8 @@
 13195,RAG203_,RAG203,5,1800000,,1300,260,,9,0,0x40000000,63,2,34,3,140,1,18,{ bonus bHit,10; bonus bCriticalRate,15; bonus4 bAutoSpell,"AL_DECAGI",1,10,1; },{},{}
 13196,Peace_Breaker_,Peace Breaker,5,1950000,,1400,250,,9,1,0x41000000,63,2,34,3,140,1,20,{ bonus bHit,-25; bonus bAspdRate,25; },{},{}
 13197,Mini_Mei,Mini Mei,5,1600000,,2500,220,,9,2,0x41000000,63,2,34,2,106,1,19,{},{},{}
-13198,Tempest_,Tempest,5,2200000,,2500,250,,9,0,0x41000000,63,2,34,2,140,1,19,{ bonus bHit,-25; bonus bCritical,10; bonus bLongAtkRate,20; },{},{}
-13199,Tempest,Tempest,5,2200000,,2500,250,,9,1,0x41000000,63,2,34,2,140,1,19,{ bonus bHit,-25; bonus bCritical,10; bonus bLongAtkRate,20; },{},{}
+13198,Tempest_,Tempest,5,2200000,,2500,250,,9,0,0x41000000,63,2,34,4,140,1,19,{ bonus bHit,-25; bonus bCritical,10; bonus bLongAtkRate,20; },{},{}
+13199,Tempest,Tempest,5,2200000,,2500,250,,9,1,0x41000000,63,2,34,4,140,1,19,{ bonus bHit,-25; bonus bCritical,10; bonus bLongAtkRate,20; },{},{}
 //===================================================================
 // Bullets
 //===================================================================
@@ -11078,7 +11078,7 @@
 22873,Sealed_Beelzebub_Scroll_II,Sealed Beelzebub Scroll II,2,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ getitem callfunc("F_Rand",22875,6238,6239,6228,6232,24231,24232,17474,6635),1; },{},{}
 22874,Sealed_Beelzebub_Card_Album,Sealed Beelzebub Card Album,2,10,,50,,,,,0xFFFFFFFF,63,2,,,,,,{/*No Info*/},{},{}
 22875,Sealed_Beelzebub_Card,Sealed Beelzebub Card,6,20,,10,,,,,,,,769,,,,,{ bonus bVariableCastrate,-15; /*Item removed on 2014-12-17*/ },{},{}
-22876,Old_Money_Pocket,Old Money Pocket,3,0,,0,,,,,,,,,,,,,{},{},{}
+22876,Old_Money_Pocket,Old Money Pocket,3,0,,0,,,,,,,,,,,,,{ Zeny += rand(500,550); },{},{}
 22881,Rope_Gallows,Rope Gallows,2,10,,0,,,,,0xFFFFFFFF,63,2,,,,,,{/*Used to catch a Lost Sheep*/},{},{}
 22882,Chocolate_Rice_Cake_Soup,Chocolate Rice Cake Soup,2,10,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ percentheal 10,10; },{},{}
 22883,September_Gift_Box_,September Gift Box,2,10,,100,,,,,0xFFFFFFFF,63,2,,,,,,{/*2 Lucky Eggs*/},{},{}
@@ -11544,13 +11544,13 @@
 28900,Guardsmen's_Shield,Guardsmen's Shield,4,20,,3000,,30,,1,0xFFFFFFFF,63,2,32,,100,1,1,{ .@r = getrefine(); skill "LG_SHIELDSPELL",1; bonus3 bAutoSpellWhenHit,"HP_ASSUMPTIO",3,(10+(.@r*10)); bonus bDef,(.@r*10); bonus bMdef,.@r; },{},{}
 28901,Cursed_Mad_Bunny,Cursed Mad Bunny,4,20,,100,,0,,0,0xFFFFFFFF,63,2,32,,1,1,1,{ bonus bAspd,3; bonus2 bAddRace,RC_All,5; bonus2 bMagicAddRace,RC_All,5; bonus bShortWeaponDamageReturn,10; autobonus2 "{ bonus bMagicDamageReturn,60; }",10,2000,BF_MAGIC,"{ specialeffect2 EF_WIND; }"; .@r = getrefine(); if(.@r>=7) { bonus bBaseAtk,5; bonus bMatk,5; } if(.@r>=9) { bonus bBaseAtk,15; bonus bMatk,15; } if(.@r>=12) { bonus bCritical,10; bonus bNoCastCancel,0; } },{},{}
 28902,Mad_Bunny_,Mad Bunny,4,20,,100,,0,,1,0xFFFFFFFF,63,2,32,,1,1,1,{ bonus2 bAddRace,RC_All,5; bonus2 bMagicAddRace,RC_All,5; bonus bShortWeaponDamageReturn,10; autobonus2 "{ bonus bMagicDamageReturn,60; }",10,2000,BF_MAGIC,"{ specialeffect2 EF_WIND; }"; .@r = getrefine(); if(.@r>=7) { bonus bBaseAtk,5; bonus bMatk,5; } if(.@r>=9) { bonus bBaseAtk,15; bonus bMatk,15; } if(.@r>=12) { bonus bCritical,10; bonus bNoCastCancel,0; } },{},{}
-28903,Scutum,Scutum,4,0,,500,,1,,1,0xFFFFFFFF,63,2,32,1,1,1,,{ .@r = getrefine(); bonus bFlee,5+(.@r*3); bonus bFlee2,1+(.@r*2); if (.@r > 10) { bonus bMaxHPrate,10; bonus bMaxSPrate,10; } },{},{}
+28903,Scutum,Scutum,4,0,,500,,1,,1,0xFFFFFFFF,63,2,32,,1,1,1,{ .@r = getrefine(); bonus bFlee,5+(.@r*3); bonus bFlee2,1+(.@r*2); if (.@r > 10) { bonus bMaxHPrate,10; bonus bMaxSPrate,10; } },{},{}
 28904,Unity_Guard,Unity Guard,4,20,,300,,60,,1,0xFFFFFFFF,63,2,32,,100,1,1,{ if(BaseLevel<100) { bonus bDef,12*getrefine(); } },{},{}
 28905,Unity_Buckler,Unity Buckler,4,20,,300,,60,,1,0xFFFFFFFF,63,2,32,,100,1,1,{ if(BaseLevel<100) { bonus bMaxSPrate,2*getrefine(); } },{},{}
-28906,Shield_Of_Flame,Shield Of Flame,4,0,,500,,80,,1,0xFFFFFFFF,63,2,32,1,90,1,,{ bonus2 bSubEle,Ele_Fire,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); } },{},{}
-28907,Shield_Of_Gust,Shield Of Gust,4,0,,500,,80,,1,0xFFFFFFFF,63,2,32,1,90,1,,{ bonus2 bSubEle,Ele_Wind,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); } },{},{}
-28908,Shield_Of_Water,Shield Of Water,4,0,,500,,80,,1,0xFFFFFFFF,63,2,32,1,90,1,,{ bonus2 bSubEle,Ele_Water,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); } },{},{}
-28909,Shield_Of_Earth,Shield Of Earth,4,0,,500,,80,,1,0xFFFFFFFF,63,2,32,1,90,1,,{ bonus2 bSubEle,Ele_Earth,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); } },{},{}
+28906,Shield_Of_Flame,Shield Of Flame,4,0,,500,,80,,1,0xFFFFFFFF,63,2,32,,90,1,1,{ bonus2 bSubEle,Ele_Fire,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); } },{},{}
+28907,Shield_Of_Gust,Shield Of Gust,4,0,,500,,80,,1,0xFFFFFFFF,63,2,32,,90,1,1,{ bonus2 bSubEle,Ele_Wind,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); } },{},{}
+28908,Shield_Of_Water,Shield Of Water,4,0,,500,,80,,1,0xFFFFFFFF,63,2,32,,90,1,1,{ bonus2 bSubEle,Ele_Water,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); } },{},{}
+28909,Shield_Of_Earth,Shield Of Earth,4,0,,500,,80,,1,0xFFFFFFFF,63,2,32,,90,1,1,{ bonus2 bSubEle,Ele_Earth,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); } },{},{}
 28910,Rectangular_Large_Sleeve,Rectangular Large Sleeve,4,20,,800,,80,,1,0xFFFFFFFF,63,2,32,,100,1,1,{ bonus bLongAtkDef,5; .@r = getrefine(); if(.@r>=5) { bonus bLongAtkDef,5; } if(.@r>=7) { bonus bLongAtkDef,10; } if(.@r>=9) { bonus bLongAtkDef,15; } },{},{}
 28913,Ultralight_Magic_Shield,Ultralight Magic Shield,4,20,,100,,50,,1,0xFFFFFFFF,63,2,32,,100,1,1,{ bonus bAspdRate,5; bonus2 bIgnoreDefClassRate,Class_Normal,10; bonus2 bSubEle,Ele_Neutral,5; .@r = getrefine(); if(.@r>=7) { bonus2 bIgnoreDefClassRate,Class_Normal,2; bonus bAspdRate,2; } if(.@r>=9) { bonus2 bIgnoreDefClassRate,Class_Normal,3; bonus bAspdRate,3; } },{},{}
 28915,Bunker_Shield,Bunker Shield,4,20,,3500,,90,,1,0xFFFFFFFF,63,2,32,,50,1,1,{ bonus2 bAddRace,RC_All,4; bonus bAspdRate,5; .@r = getrefine(); if(.@r>=5) { bonus2 bAddRace,RC_All,.@r; } },{},{}

+ 11 - 1
db/re/mob_db.txt

@@ -3034,7 +3034,17 @@
 //3874,AB_MOB_048
 //3875,AB_MOB_049
 //3876,AB_MOB_050
-
+//3877,E_NYAIL_PIG
+//3878,E_PIT
+//3879,E_SEA_WORMS
+//3880,E_SMALL_SWIRL
+//3881,E_RIPE_WATERMELON
+//3882,E_MD_NYAILO
+//3883,E_MD_NYAILO_LEG
+//3884,E_MD_S_TREASURE_BOX
+//3885,E_MD_B_TREASURE_BOX
+//3886,E_MD_BOX_PUPPET
+//3887,E_MD_DEPRESS_SOUL
 //3888,TW_I_QUEEN_SCARABA
 //3889,TW_GIOIA
 //3890,TW_TIMEHOLDER

+ 102 - 0
doc/achievements.txt

@@ -0,0 +1,102 @@
+//===== rAthena Documentation ================================
+//= Achievement Database Structure
+//===== By: ==================================================
+//= rAthena Dev Team
+//===== Last Updated: ========================================
+//= 20170531
+//===== Description: =========================================
+//= Explanation of the achievements_db.yml file and structure.
+//============================================================
+
+---------------------------------------
+
+ID: Unique achievement ID.
+
+---------------------------------------
+
+Group: Achievement group type. Each achievement type calls a specific objective check.
+Valid groups:
+	AG_ADD_FRIEND - Triggered when a player adds a friend.
+	AG_ADVENTURE - Does not trigger automatically. These are triggered by the achievementcomplete script command.
+	AG_BABY - Triggered when a player becomes a baby job.
+	AG_BATTLE - Triggered when a player kills a monster.
+	AG_CHATTING - Unknown.
+	AG_CHATTING_COUNT - Triggered when a player has a chatroom open and others join.
+	AG_CHATTING_CREATE - Triggered when a player creates a chatroom.
+	AG_CHATTING_DYING - Triggered when a player creates a chatroom and dies with it open.
+	AG_EAT - Unknown.
+	AG_GET_ITEM - Triggered when a player gets an item that has a specific sell value.
+	AG_GET_ZENY - Triggered when a player gets a specific amount of zeny at once.
+	AG_GOAL_ACHIEVE - Triggered when a player's achievement rank levels up.
+	AG_GOAL_LEVEL - Triggered when a player's base level or job level changes.
+	AG_GOAL_STATUS - Triggered when a player's base stats changes.
+	AG_HEAR - Unknown.
+	AG_JOB_CHANGE - Triggered when a player's job changes.
+	AG_MARRY - Triggered when two players get married.
+	AG_PARTY - Triggered when a player creates a party.
+	AG_ENCHANT_FAIL - Triggered when a player fails to refine an equipment.
+	AG_ENCHANT_SUCCESS - Triggered when a player successfully refines an equipment.
+	AG_SEE - Unknown.
+	AG_SPEND_ZENY - Triggered when a player spends any amount of zeny on vendors.
+	AG_TAMING - Triggered when a player tames a monster.
+
+---------------------------------------
+
+Name: Achievement name. Not read into source but used for quick look ups.
+
+---------------------------------------
+
+Target: A list of monster ID and count values that the achievement requires.
+		The target count can also be used for achievements that keep a counter while not being related to monster kills.
+		Capped at MAX_ACHIEVEMENT_OBJECTIVES.
+
+Example:
+  // Player must kill 5 Scorpions and 10 Poring.
+  Target:
+    - MobID: 1001
+      Count: 5
+    - MobID: 1002
+      Count: 10
+
+Example 2:
+  // Player must have 100 or more of ARG0 value. Using the count target value is useful for achievements that are increased in increments
+  // and not checked for a total (UI_Type = 1).
+  // IE: In the achievement_list.lub file, UI_Type 0 is displayed as non-incremental while 1 shows a progress bar of completion for the achievement.
+  Condition: " ARG0 >= 100 "
+  Target:
+    Count: 100
+
+---------------------------------------
+
+Condition: A conditional statement that must be met for the achievement to be considered complete. Accepts script constants, player variables, and
+		   ARGX (where X is the argument vector value). The ARGX values are sent from the server to the achievement script engine on special events.
+		   Below are two examples of how the ARGX feature works.
+
+Example:
+	// This function will send 1 argument (ARG0) with a value of i + 1 when a friend is added.
+	achievement_update_objective(f_sd, AG_ADD_FRIEND, 1, i + 1);
+
+Example 2:
+	// This function will send 2 arguments (ARG0 and ARG1) with values of weapon level and refine level, respectively, when an equipment is
+	// successfully refined.
+	achievement_update_objective(sd, AG_REFINE_SUCCESS, 2, sd->inventory_data[i]->wlv, sd->inventory.u.items_inventory[i].refine);
+
+---------------------------------------
+
+Map: A map name that is used for the AG_CHATTING type which increments the counter based on the player's map.
+
+---------------------------------------
+
+Dependent: A list of achievement IDs that need to be completed before this achievement is considered complete.
+
+---------------------------------------
+
+Reward: A list of rewards that are given on completion. All fields are optional.
+  ItemID: Item ID
+  Amount:	Amount of Item ID (default 1)
+  Script: Bonus Script
+  TitleID: Title ID
+
+---------------------------------------
+
+Score: Achievement points that are given on completion.

+ 4 - 4
doc/atcommands.txt

@@ -1320,12 +1320,12 @@ This will also send a packet to clients causing them to close.
 @reloadmobdb
 @reloadmotd
 @reloadmsgconf
-@reloadpacketdb
 @reloadpcdb
 @reloadquestdb
 @reloadscript
 @reloadskilldb
 @reloadstatusdb
+@reloadachievementdb
 
 Reloads a database or configuration file.
 
@@ -1333,10 +1333,10 @@ Databases:
 -- instancedb: Instance Database
 -- itemdb: Item Database
 -- mobdb: Monster Database
--- packetdb: Packet Database
 -- questdb: Quest Database
 -- script: NPC Scripts
 -- skilldb: Skill Database
+-- achievementdb: Achievement Database
 
 Configuration files:
 -- atcommand: Atcommand Settings
@@ -1354,12 +1354,12 @@ Affected files:
 -- mobdb: mob_db.txt, mob_item_ratio.txt, mob_chat_db.txt, mob_avail.txt, mob_race2_db.txt, mob_branch.txt, mob_poring.txt, mob_boss.txt, mob_pouch.txt, mob_classchange.txt, pet_db.txt, homunculus_db.txt, homun_skill_tree.txt, exp_homun.txt, mercenary_db.txt, mercenary_skill_db.txt, elemental_db.txt, elemental_skill_db.txt
 -- motd: motd.txt
 -- msgconf: atcommand_athena.conf
--- packetdb: packet_db.txt
 -- pcdb: statpoint.txt, job_exp.txt, skill_tree.txt, attr_fix.txt, job_db1.txt, job_db2.txt, job_basehpsp_db.txt, job_maxhpsp_db.txt, job_param_db.txt, level_penalty.txt
 -- questdb: quest_db.txt
 -- script: /npc/*.txt, /npc/*.conf
 -- skilldb: skill_db.txt, const.txt, skill_require_db.txt, skill_cast_db.txt, skill_castnodex_db.txt, skill_nocast_db.txt, skill_copyable_db.txt, skill_improvise_db.txt, skill_changematerial_db.txt, skill_nonearnpc_db.txt, skill_damage_db.txt, skill_unit_db.txt, abra_db.txt, create_arrow_db.txt, produce_db.txt, spellbook_db.txt, magicmushroom_db.txt
--- statusdb: attr_fix.txt, size_fix.txt, refine_db.tx
+-- statusdb: attr_fix.txt, size_fix.txt, refine_db.txt
+-- achievementdb: achievement_db.conf
 
 Restriction:
 	- Used from 'atcommand' or 'useatcmd'. For @reload & @reloadscript

+ 27 - 8
doc/packet_interserv.txt

@@ -47,9 +47,9 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
 
 0x2713:
 	Type: AH
-	Structure: <cmd>.W <aid>.L <login_id1>.L <login_id2>.L <sex>.B <auth>.B <request_id>.L <version>.L <clienttype>.B
-	index: 0,2,6,10,14,15,16,20,24
-	len: 25
+	Structure: <cmd>.W <aid>.L <login_id1>.L <login_id2>.L <sex>.B <auth>.B <request_id>.L <clienttype>.B
+	index: 0,2,6,10,14,15,16,20
+	len: 21
 	parameter:
 		- cmd : packet identification (0x2713)
 		- aid : account identification
@@ -58,7 +58,6 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
 		- sex: the sex of the account
 		- ok : 1=auth failed, 1=ok
 		- request_id: unknown @FIXME
-		- version: client version, (clientinfo version)
 		- clienttype: unknown @FIXME
 	desc:
 		- Acknowledge the authentication request from char-serv
@@ -1190,6 +1189,27 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
 	desc:
 		- Requests to the inter server to save a character's quest log entries.
 
+0x3062
+	Type: ZI
+	Structure: <cmd>.W <cid>.L
+	index: 0,2
+	len: 6
+	parameter:
+		- cmd : packet identification (0x3062)
+		- cid
+	desc:
+		- Requests a character's achievement log entries to the inter server.
+
+0x3063
+	Type: ZI
+	Structure: <cmd>.W <len>.W <cid>.L <achievement_log>.?B
+	index: 0,2,4,8
+	len: variable: 8+count
+	parameter:
+		- cmd : packet identification (0x3063)
+	desc:
+		- Requests to the inter server to save a character's achievement log entries.
+
 0x3070
 	Type: ZI
 	Structure: <cmd>.W <size>.W <merc>.?B
@@ -2769,16 +2789,15 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
 
 0x2b02
 	Type: ZA
-	Structure: <cmd>.W <id>.L <login_id1>.L <login_id2>.L <s_ip>.L <packet_ver>.B
-	index: 0,2,6,10,14,18
-	len: 19
+	Structure: <cmd>.W <id>.L <login_id1>.L <login_id2>.L <s_ip>.L
+	index: 0,2,6,10,14
+	len: 18
 	parameter:
 		- cmd : packet identification (0x2b02)
 		- id
 		- login_id1
 		- login_id2
 		- s_ip
-		- packet_ver
 	desc:
 		- chrif_charselectreq
 

+ 89 - 14
doc/script_commands.txt

@@ -1037,6 +1037,7 @@ From here on, we will have the commands sorted as follow:
 12.- Mercenary commands.
 13.- Party commands.
 14.- Channel commands.
+15.- Achievement commands.
 
 =====================
 |1.- Basic commands.|
@@ -3723,18 +3724,6 @@ The renewal feature to check is determined by type.
  4 - RENEWAL_LVDMG (renewal level modifier on damage)
  5 - RENEWAL_ASPD (renewal ASPD)
 
----------------------------------------
-
-*is_clientver(<type>,<value>{,<char id>})
-
-Checks a character's client version against a specified value. If no char id is
-given, the command will run for the invoking character. The function will return
-1 if the player's version is greater than or equal to the value, and 0 otherwise.
-
-Available types are:
- 0 - version number (packet_db_ver)
- 1 - client date (YYYYMMDD)
-
 ---------------------------------------
 \\
 3,1.- Item-related commands
@@ -6415,9 +6404,22 @@ This command works almost like sleep2, but displays a progress bar
 above the head of the currently attached character (like cast bar).
 Once the given amount of seconds passes, the script resumes. If the
 character moves while the progress bar progresses, it is aborted and
-the script ends. The color format is in RGB (0xRRGGBB). The color is
+the script ends. The color format is in RGB (RRGGBB). The color is
 currently ignored by the client and appears always green.
 
+---------------------------------------
+
+*progressbar_npc "<color>",<seconds>{,<"NPC Name">};
+
+This command works like progressbar, but displays a progress bar
+above the head of the currently attached (or given) NPC. Once the
+given amount of seconds passes, the script resumes. The color format
+is in RGB (RRGGBB). The color is currently ignored by the client and
+appears always green.
+
+Note: If a player is attached to the NPC, they are detached from the NPC
+as soon as the progress bar activates.
+
 ---------------------------------------
 //
 5,1.- End of time-related commands
@@ -7406,7 +7408,7 @@ This command will make a <GID> stop attacking.
 
 ---------------------------------------
 
-*unitstopwalk <GID>;
+*unitstopwalk <GID>{,<flag>};
 
 This command will make a <GID> stop moving.
 
@@ -7414,6 +7416,14 @@ Note: If this is called from OnTouch, then the walktimer attached to the unit is
 removed from OnTouch which causes this command to not stop the unit from walking.
 Suggest to use 'unitblockmove' to forcefully stop the unit with OnTouch.
 
+The <flag> value affects how the unit is stopped. The following flags are bitwise
+values (can be combined using the pipe operator):
+	USW_NONE = Unit will keep walking to their original destination.
+	USW_FIXPOS = Issue a fixpos packet afterwards.
+	USW_MOVE_ONCE = Force the unit to move one cell if it hasn't yet.
+	USW_MOVE_FULL_CELL = Enable moving to the next cell when unit was already half-way there (may cause on-touch/place side-effects, such as a scripted map change).
+	USW_FORCE_STOP = Force stop moving.
+
 ---------------------------------------
 
 *unittalk <GID>,"<text>"{,flag};
@@ -9748,3 +9758,68 @@ local map channel.
 Returns 0 on success.
 
 ---------------------------------------
+
+============================
+|15.- Achievement commands.|
+============================
+---------------------------------------
+
+*achievementadd(<achievement id>{,<char id>})
+
+This function will add an achievement to the player's log for the attached
+player or the supplied <char id>. The objective requirements are not ignored
+when using this function.
+Returns true on success and false on failure.
+
+---------------------------------------
+
+*achievementremove(<achievement id>{,<char id>})
+
+This function will remove an achievement from the player's log for the attached
+player or the supplied <char id>.
+Returns true on success and false on failure.
+
+---------------------------------------
+
+*achievementinfo(<achievement id>,<type>{,<char id>})
+
+This function will return the specified <type> value for an achievement of the
+attached player or the supplied <char id>. If the player doesn't have the
+achievement active (no progress has been made), if the achievement doesn't
+exist -1 will be returned, or -2 will be returned on any other error such as
+an invalid <type>.
+
+Valid types:
+- ACHIEVEINFO_COUNT1
+- ACHIEVEINFO_COUNT2
+- ACHIEVEINFO_COUNT3
+- ACHIEVEINFO_COUNT4
+- ACHIEVEINFO_COUNT5
+- ACHIEVEINFO_COUNT6
+- ACHIEVEINFO_COUNT7
+- ACHIEVEINFO_COUNT8
+- ACHIEVEINFO_COUNT9
+- ACHIEVEINFO_COUNT10
+- ACHIEVEINFO_COMPLETE
+- ACHIEVEINFO_COMPLETEDATE
+- ACHIEVEINFO_GOTREWARD
+- ACHIEVEINFO_LEVEL (<achievement id> is useless for this)
+- ACHIEVEINFO_SCORE (<achievement id> is useless for this)
+
+---------------------------------------
+
+*achievementcomplete(<achievement id>{,<char id>})
+
+This function will complete an achievement for the attached player or the supplied
+<char id>. The objective requirements are ignored when using this function.
+Returns true on success and false on failure.
+
+---------------------------------------
+
+*achievementexists(<achievement id>{,<char id>});
+
+This function will return if the achievement exists on the player or the supplied
+<char id>.
+Returns true on success and false on failure.
+
+---------------------------------------

+ 2 - 1
npc/re/guides/navigation.txt

@@ -13,11 +13,12 @@
 //===== Additional Comments: ================================= 
 //= 1.0 First version.
 //= 1.1 Added 'is_clientver' command. [Euphy]
+//= 1.2 Dropped 'is_clientver' command. [Lemongrass]
 //============================================================ 
 
 function	script	F_Navi	{
 
-	if (!is_clientver(1,20111010))
+	if ( PACKETVER < 20111010 )
 		set .@disabled,1;
 
 	// This function takes 0 ~ 3 parameters.

+ 278 - 0
npc/re/other/achievements.txt

@@ -0,0 +1,278 @@
+//===== rAthena Script =======================================
+//= Adventure Achievements
+//===== Description: =========================================
+//= Spawns Adventure group type treasure chests.
+//===== Changelogs: ==========================================
+//= 1.0 Initial release. [Aleos]
+//============================================================
+
+-	script	ach_treasure#core	-1,{
+	if (strnpcinfo(3) == "")
+		end;
+	achievementcomplete(atoi(strnpcinfo(3)));
+	classchange HIDDEN_WARP_NPC;
+	initnpctimer;
+	end;
+
+OnTouch:
+	if (getnpctimer(1)) // Don't trigger touch if the delay timer is active.
+		end;
+	if (achievementexists(atoi(strnpcinfo(3)))) // Don't trigger if the player has already completed.
+		end;
+	classchange 4_TREASURE_BOX,"",bc_self;
+	end;
+
+OnTimer5000:
+	stopnpctimer;
+	end;
+}
+
+//-----------------
+// --- Dungeons ---
+//-----------------
+
+// Abbey Underground
+abbey03,26,72,0	duplicate(ach_treasure#core)	#abb_ach1::120110	HIDDEN_WARP_NPC,5,5
+
+// Abyss Lake
+abyss_03,86,55,0	duplicate(ach_treasure#core)	#aby_ach1::120111	HIDDEN_WARP_NPC,5,5
+
+// Amatsu Dungeon
+ama_dun03,60,163,0	duplicate(ach_treasure#core)	#ama_ach1::120113	HIDDEN_WARP_NPC,5,5
+
+// Ant Hell
+anthell02,253,41,0	duplicate(ach_treasure#core)	#ant_ach1::120114	HIDDEN_WARP_NPC,5,5
+
+// Ayothaya Dungeon
+ayo_dun02,150,256,0	duplicate(ach_treasure#core)	#ayo_ach1::120115	HIDDEN_WARP_NPC,5,5
+
+// Bifrost
+ecl_tdun04,37,37,0	duplicate(ach_treasure#core)	#ecl_ach1::120121	HIDDEN_WARP_NPC,5,5
+
+// Brasilis Dungeon
+bra_dun02,171,121,0	duplicate(ach_treasure#core)	#bra_ach1::120117	HIDDEN_WARP_NPC,5,5
+
+// Byalan Dungeon
+iz_dun05,64,223,0	duplicate(ach_treasure#core)	#iz_ach2::120141	HIDDEN_WARP_NPC,5,5
+
+// Clock Tower
+c_tower4,37,158,0	duplicate(ach_treasure#core)	#ct_ach1::120112	HIDDEN_WARP_NPC,5,5
+alde_dun04,90,107,0	duplicate(ach_treasure#core)	#ct_ach2::120118	HIDDEN_WARP_NPC,5,5
+
+// Coal Mine
+mjo_dun03,76,220,0	duplicate(ach_treasure#core)	#mjo_ach1::120136	HIDDEN_WARP_NPC,5,5
+
+// Comodo Dungeon
+beach_dun3,102,71,0	duplicate(ach_treasure#core)	#bea_ach1::120116	HIDDEN_WARP_NPC,5,5
+
+// Einbech
+ein_dun02,31,255,0	duplicate(ach_treasure#core)	#eind_ach1::120122	HIDDEN_WARP_NPC,5,5
+
+// Geffen Dungeon
+gef_dun02,222,163,0	duplicate(ach_treasure#core)	#gefd_ach1::120123	HIDDEN_WARP_NPC,5,5
+
+// Glastheim
+gl_cas02,53,151,0	duplicate(ach_treasure#core)	#gl_ach1::120124	HIDDEN_WARP_NPC,5,5
+gl_sew04,288,6,0	duplicate(ach_treasure#core)	#gl_ach2::120125	HIDDEN_WARP_NPC,5,5
+gl_knt02,126,235,0	duplicate(ach_treasure#core)	#gl_ach3::120126	HIDDEN_WARP_NPC,5,5
+gl_prison1,125,159,0	duplicate(ach_treasure#core)	#gl_ach4:120127	HIDDEN_WARP_NPC,5,5
+
+// Gonryun Dungeon
+gon_dun03,167,232,0	duplicate(ach_treasure#core)	#gon_ach1::120128	HIDDEN_WARP_NPC,5,5
+
+// Istana
+dew_dun02,87,272,0	duplicate(ach_treasure#core)	#dew_ach1::120119	HIDDEN_WARP_NPC,5,5
+
+// Labyrinth
+prt_maze03,11,14,0	duplicate(ach_treasure#core)	#maze_ach1::120140	HIDDEN_WARP_NPC,5,5
+
+// Louyang Dungeon
+lou_dun03,29,228,0	duplicate(ach_treasure#core)	#lou_ach1::120134	HIDDEN_WARP_NPC,5,5
+
+// Nogg Road
+mag_dun02,192,72,0	duplicate(ach_treasure#core)	#mag_ach1::120135	HIDDEN_WARP_NPC,5,5
+
+// Orc Dungeon
+orcsdun02,32,72,0	duplicate(ach_treasure#core)	#orc_ach1::120138	HIDDEN_WARP_NPC,5,5
+
+// Payon Dungeon
+pay_dun04,120,124,0	duplicate(ach_treasure#core)	#payd_ach1::120139	HIDDEN_WARP_NPC,5,5
+
+// Prontera Culvert
+prt_sewb4,19,183,0	duplicate(ach_treasure#core)	#iz_ach1::120131	HIDDEN_WARP_NPC,5,5
+
+// Pyramid
+moc_pryd06,102,121,0	duplicate(ach_treasure#core)	#pyr_ach1::120137	HIDDEN_WARP_NPC,5,5
+
+// Rachel Dungeon
+ice_dun03,44,261,0	duplicate(ach_treasure#core)	#rad_ach1::120129	HIDDEN_WARP_NPC,5,5
+
+// Robot Factory
+kh_dun02,70,106,0	duplicate(ach_treasure#core)	#jup_ach1::120132	HIDDEN_WARP_NPC,5,5
+
+// Scaraba Hall
+dic_dun03,216,211,0	duplicate(ach_treasure#core)	#dic_ach1::120120	HIDDEN_WARP_NPC,5,5
+
+// Somatology Lab
+lhz_dun03,240,221,0	duplicate(ach_treasure#core)	#lhzd_ach1::120133	HIDDEN_WARP_NPC,5,5
+
+// Sphinx
+in_sphinx5,154,107,0	duplicate(ach_treasure#core)	#sph_ach1::120130	HIDDEN_WARP_NPC,5,5
+
+// Sunken Ship
+treasure02,18,142,0	duplicate(ach_treasure#core)	#iz_ach3::120144	HIDDEN_WARP_NPC,5,5
+
+// Thanatos Tower
+tha_t06,150,176,0	duplicate(ach_treasure#core)	#tha_ach1::120142	HIDDEN_WARP_NPC,5,5
+
+// Thors Volcano
+thor_v03,220,221,0	duplicate(ach_treasure#core)	#thor_ach1::120143	HIDDEN_WARP_NPC,5,5
+
+// Toy Factory
+xmas_dun02,120,224,0	duplicate(ach_treasure#core)	#xmas_ach1::120146	HIDDEN_WARP_NPC,5,5
+
+// Turtle Island Dungeon
+tur_dun04,134,130,0	duplicate(ach_treasure#core)	#tur_ach1::120145	HIDDEN_WARP_NPC,5,5
+
+//---------------
+// --- Fields ---
+//---------------
+
+// Comodo
+cmd_fild01,112,200,0	duplicate(ach_treasure#core)	#cmd_ach1::120044	HIDDEN_WARP_NPC,5,5
+cmd_fild02,86,94,0	duplicate(ach_treasure#core)	#cmd_ach2::120045	HIDDEN_WARP_NPC,5,5
+cmd_fild03,144,190,0	duplicate(ach_treasure#core)	#cmd_ach3::120046	HIDDEN_WARP_NPC,5,5
+cmd_fild04,151,191,0	duplicate(ach_treasure#core)	#cmd_ach4::120047	HIDDEN_WARP_NPC,5,5
+cmd_fild06,221,108,0	duplicate(ach_treasure#core)	#cmd_ach5::120048	HIDDEN_WARP_NPC,5,5
+cmd_fild07,269,322,0	duplicate(ach_treasure#core)	#cmd_ach6::120049	HIDDEN_WARP_NPC,5,5
+cmd_fild08,181,136,0	duplicate(ach_treasure#core)	#cmd_ach7::120050	HIDDEN_WARP_NPC,5,5
+cmd_fild09,211,266,0	duplicate(ach_treasure#core)	#cmd_ach8::120051	HIDDEN_WARP_NPC,5,5
+
+// Einbroch
+ein_fild01,266,277,0	duplicate(ach_treasure#core)	#ein_ach1::120067	HIDDEN_WARP_NPC,5,5
+ein_fild03,99,332,0	duplicate(ach_treasure#core)	#ein_ach2::120068	HIDDEN_WARP_NPC,5,5
+ein_fild04,334,305,0	duplicate(ach_treasure#core)	#ein_ach3::120069	HIDDEN_WARP_NPC,5,5
+ein_fild05,337,233,0	duplicate(ach_treasure#core)	#ein_ach4::120070	HIDDEN_WARP_NPC,5,5
+ein_fild06,174,245,0	duplicate(ach_treasure#core)	#ein_ach5::120071	HIDDEN_WARP_NPC,5,5
+ein_fild07,188,50,0	duplicate(ach_treasure#core)	#ein_ach6::120072	HIDDEN_WARP_NPC,5,5
+ein_fild08,258,78,0	duplicate(ach_treasure#core)	#ein_ach7::120073	HIDDEN_WARP_NPC,5,5
+ein_fild09,330,76,0	duplicate(ach_treasure#core)	#ein_ach8::120074	HIDDEN_WARP_NPC,5,5
+
+// Geffen
+gef_fild00,74,119,0	duplicate(ach_treasure#core)	#gef_ach1::120011	HIDDEN_WARP_NPC,5,5
+gef_fild01,223,223,0	duplicate(ach_treasure#core)	#gef_ach2::120012	HIDDEN_WARP_NPC,5,5
+gef_fild05,202,292,0	duplicate(ach_treasure#core)	#gef_ach3::120013	HIDDEN_WARP_NPC,5,5
+gef_fild06,279,104,0	duplicate(ach_treasure#core)	#gef_ach4::120014	HIDDEN_WARP_NPC,5,5
+gef_fild07,181,250,0	duplicate(ach_treasure#core)	#gef_ach5::120015	HIDDEN_WARP_NPC,5,5
+gef_fild09,170,73,0	duplicate(ach_treasure#core)	#gef_ach6::120016	HIDDEN_WARP_NPC,5,5
+gef_fild11,238,249,0	duplicate(ach_treasure#core)	#gef_ach7::120017	HIDDEN_WARP_NPC,5,5
+
+// Hugel
+hu_fild01,347,312,0	duplicate(ach_treasure#core)	#hu_ach1::120062	HIDDEN_WARP_NPC,5,5
+hu_fild02,80,152,0	duplicate(ach_treasure#core)	#hu_ach2::120063	HIDDEN_WARP_NPC,5,5
+hu_fild04,322,313,0	duplicate(ach_treasure#core)	#hu_ach3::120064	HIDDEN_WARP_NPC,5,5
+hu_fild06,204,228,0	duplicate(ach_treasure#core)	#hu_ach4::120065	HIDDEN_WARP_NPC,5,5
+hu_fild05,197,210,0	duplicate(ach_treasure#core)	#hu_ach5::120066	HIDDEN_WARP_NPC,5,5
+
+// Laphine
+ecl_fild01,155,322,0	duplicate(ach_treasure#core)	#ecl_ach1::120090	HIDDEN_WARP_NPC,5,5
+bif_fild01,147,64,0	duplicate(ach_treasure#core)	#ecl_ach2::120091	HIDDEN_WARP_NPC,5,5
+bif_fild02,155,322,0	duplicate(ach_treasure#core)	#ecl_ach3::120092	HIDDEN_WARP_NPC,5,5
+spl_fild01,335,315,0	duplicate(ach_treasure#core)	#ecl_ach4::120093	HIDDEN_WARP_NPC,5,5
+spl_fild02,153,358,0	duplicate(ach_treasure#core)	#ecl_ach5::120094	HIDDEN_WARP_NPC,5,5
+spl_fild03,61,286,0	duplicate(ach_treasure#core)	#ecl_ach6::120095	HIDDEN_WARP_NPC,5,5
+
+// Lighthalzen
+lhz_fild01,118,73,0	duplicate(ach_treasure#core)	#lhz_ach1::120075	HIDDEN_WARP_NPC,5,5
+lhz_fild02,239,243,0	duplicate(ach_treasure#core)	#lhz_ach2::120076	HIDDEN_WARP_NPC,5,5
+lhz_fild03,313,132,0	duplicate(ach_treasure#core)	#lhz_ach3::120077	HIDDEN_WARP_NPC,5,5
+
+// Manuk
+man_fild01,41,172,0	duplicate(ach_treasure#core)	#man_ach1::120096	HIDDEN_WARP_NPC,5,5
+man_fild02,268,355,0	duplicate(ach_treasure#core)	#man_ach2::120097	HIDDEN_WARP_NPC,5,5
+man_fild03,198,91,0	duplicate(ach_treasure#core)	#man_ach3::120098	HIDDEN_WARP_NPC,5,5
+dic_fild01,227,82,0	duplicate(ach_treasure#core)	#man_ach4::120099	HIDDEN_WARP_NPC,5,5
+dic_fild02,147,196,0	duplicate(ach_treasure#core)	#man_ach5::120100	HIDDEN_WARP_NPC,5,5
+
+// Misc
+ama_fild01,187,337,0	duplicate(ach_treasure#core)	#misc_ach1::120101	HIDDEN_WARP_NPC,5,5
+gon_fild01,171,332,0	duplicate(ach_treasure#core)	#misc_ach2::120102	HIDDEN_WARP_NPC,5,5
+lou_fild01,104,232,0	duplicate(ach_treasure#core)	#misc_ach3::120103	HIDDEN_WARP_NPC,5,5
+ayo_fild01,289,70,0	duplicate(ach_treasure#core)	#misc_ach4::120104	HIDDEN_WARP_NPC,5,5
+mosk_fild02,176,77,0	duplicate(ach_treasure#core)	#misc_ach5::120105	HIDDEN_WARP_NPC,5,5
+bra_fild01,99,193,0	duplicate(ach_treasure#core)	#misc_ach6::120106	HIDDEN_WARP_NPC,5,5
+dew_fild01,175,287,0	duplicate(ach_treasure#core)	#misc_ach7::120107	HIDDEN_WARP_NPC,5,5
+ma_fild01,308,206,0	duplicate(ach_treasure#core)	#misc_ach8::120108	HIDDEN_WARP_NPC,5,5
+ma_fild02,176,77,0	duplicate(ach_treasure#core)	#misc_ach9::120109	HIDDEN_WARP_NPC,5,5
+
+// Mjolnir
+mjolnir_01,47,60,0	duplicate(ach_treasure#core)	#nmjo_ach1::120032	HIDDEN_WARP_NPC,5,5
+mjolnir_02,77,49,0	duplicate(ach_treasure#core)	#nmjo_ach2::120033	HIDDEN_WARP_NPC,5,5
+mjolnir_03,190,200,0	duplicate(ach_treasure#core)	#nmjo_ach3::120034	HIDDEN_WARP_NPC,5,5
+mjolnir_04,201,146,0	duplicate(ach_treasure#core)	#nmjo_ach4::120035	HIDDEN_WARP_NPC,5,5
+mjolnir_05,43,327,0	duplicate(ach_treasure#core)	#nmjo_ach5::120036	HIDDEN_WARP_NPC,5,5
+mjolnir_06,162,290,0	duplicate(ach_treasure#core)	#smjo_ach1::120037	HIDDEN_WARP_NPC,5,5
+mjolnir_07,321,127,0	duplicate(ach_treasure#core)	#smjo_ach2::120038	HIDDEN_WARP_NPC,5,5
+mjolnir_08,175,225,0	duplicate(ach_treasure#core)	#smjo_ach3::120039	HIDDEN_WARP_NPC,5,5
+mjolnir_09,299,123,0	duplicate(ach_treasure#core)	#smjo_ach4::120040	HIDDEN_WARP_NPC,5,5
+mjolnir_10,353,371,0	duplicate(ach_treasure#core)	#smjo_ach5::120041	HIDDEN_WARP_NPC,5,5
+mjolnir_11,329,182,0	duplicate(ach_treasure#core)	#smjo_ach6::120042	HIDDEN_WARP_NPC,5,5
+mjolnir_12,110,298,0	duplicate(ach_treasure#core)	#smjo_ach7::120043	HIDDEN_WARP_NPC,5,5
+
+// Morocc
+moc_fild11,188,218,0	duplicate(ach_treasure#core)	#moc_ach1::120018	HIDDEN_WARP_NPC,5,5
+moc_fild12,234,96,0	duplicate(ach_treasure#core)	#moc_ach2::120019	HIDDEN_WARP_NPC,5,5
+moc_fild13,290,207,0	duplicate(ach_treasure#core)	#moc_ach3::120020	HIDDEN_WARP_NPC,5,5
+moc_fild16,196,108,0	duplicate(ach_treasure#core)	#moc_ach4::120021	HIDDEN_WARP_NPC,5,5
+moc_fild17,269,105,0	duplicate(ach_treasure#core)	#moc_ach5::120022	HIDDEN_WARP_NPC,5,5
+moc_fild18,54,284,0	duplicate(ach_treasure#core)	#moc_ach6::120023	HIDDEN_WARP_NPC,5,5
+
+// Payon
+pay_fild01,167,243,0	duplicate(ach_treasure#core)	#pay_ach1::120024	HIDDEN_WARP_NPC,5,5
+pay_fild02,105,240,0	duplicate(ach_treasure#core)	#pay_ach2::120025	HIDDEN_WARP_NPC,5,5
+pay_fild03,144,97,0	duplicate(ach_treasure#core)	#pay_ach3::120026	HIDDEN_WARP_NPC,5,5
+pay_fild04,257,95,0	duplicate(ach_treasure#core)	#pay_ach4::120027	HIDDEN_WARP_NPC,5,5
+pay_fild07,365,37,0	duplicate(ach_treasure#core)	#pay_ach5::120028	HIDDEN_WARP_NPC,5,5
+pay_fild08,237,345,0	duplicate(ach_treasure#core)	#pay_ach6::120029	HIDDEN_WARP_NPC,5,5
+pay_fild09,251,42,0	duplicate(ach_treasure#core)	#pay_ach7::120030	HIDDEN_WARP_NPC,5,5
+pay_fild10,196,38,0	duplicate(ach_treasure#core)	#pay_ach8::120031	HIDDEN_WARP_NPC,5,5
+
+// Prontera
+prt_fild01,147,126,0	duplicate(ach_treasure#core)	#prt_ach1::120001	HIDDEN_WARP_NPC,5,5
+prt_fild02,140,219,0	duplicate(ach_treasure#core)	#prt_ach2::120002	HIDDEN_WARP_NPC,5,5
+prt_fild03,172,139,0	duplicate(ach_treasure#core)	#prt_ach3::120003	HIDDEN_WARP_NPC,5,5
+prt_fild04,119,291,0	duplicate(ach_treasure#core)	#prt_ach4::120004	HIDDEN_WARP_NPC,5,5
+prt_fild05,190,291,0	duplicate(ach_treasure#core)	#prt_ach5::120005	HIDDEN_WARP_NPC,5,5
+prt_fild06,296,303,0	duplicate(ach_treasure#core)	#prt_ach6::120006	HIDDEN_WARP_NPC,5,5
+prt_fild07,45,104,0	duplicate(ach_treasure#core)	#prt_ach7::120007	HIDDEN_WARP_NPC,5,5
+prt_fild08,203,223,0	duplicate(ach_treasure#core)	#prt_ach8::120008	HIDDEN_WARP_NPC,5,5
+prt_fild09,37,354,0	duplicate(ach_treasure#core)	#prt_ach9::120009	HIDDEN_WARP_NPC,5,5
+prt_fild10,177,206,0	duplicate(ach_treasure#core)	#prt_ach10::12010	HIDDEN_WARP_NPC,5,5
+
+// Rachel
+ra_fild01,138,166,0	duplicate(ach_treasure#core)	#ra_ach1::120078	HIDDEN_WARP_NPC,5,5
+ra_fild03,224,275,0	duplicate(ach_treasure#core)	#ra_ach2::120079	HIDDEN_WARP_NPC,5,5
+ra_fild08,326,45,0	duplicate(ach_treasure#core)	#ra_ach3::120080	HIDDEN_WARP_NPC,5,5
+ra_fild12,352,165,0	duplicate(ach_treasure#core)	#ra_ach4::120081	HIDDEN_WARP_NPC,5,5
+ra_fild04,92,302,0	duplicate(ach_treasure#core)	#ra_ach5::120082	HIDDEN_WARP_NPC,5,5
+ra_fild05,59,59,0	duplicate(ach_treasure#core)	#ra_ach6::120083	HIDDEN_WARP_NPC,5,5
+ra_fild06,362,230,0	duplicate(ach_treasure#core)	#ra_ach7::120084	HIDDEN_WARP_NPC,5,5
+
+// Veins
+ve_fild01,180,234,0	duplicate(ach_treasure#core)	#ve_ach1::120085	HIDDEN_WARP_NPC,5,5
+ve_fild02,65,194,0	duplicate(ach_treasure#core)	#ve_ach2::120086	HIDDEN_WARP_NPC,5,5
+ve_fild03,197,242,0	duplicate(ach_treasure#core)	#ve_ach3::120087	HIDDEN_WARP_NPC,5,5
+ve_fild04,288,279,0	duplicate(ach_treasure#core)	#ve_ach4::120088	HIDDEN_WARP_NPC,5,5
+ve_fild07,33,113,0	duplicate(ach_treasure#core)	#ve_ach5::120089	HIDDEN_WARP_NPC,5,5
+
+// Yuno
+yuno_fild01,284,138,0	duplicate(ach_treasure#core)	#yuno_ach1::120052	HIDDEN_WARP_NPC,5,5
+yuno_fild12,76,268,0	duplicate(ach_treasure#core)	#yuno_ach2::120053	HIDDEN_WARP_NPC,5,5
+yuno_fild02,142,191,0	duplicate(ach_treasure#core)	#yuno_ach3::120054	HIDDEN_WARP_NPC,5,5
+yuno_fild03,135,329,0	duplicate(ach_treasure#core)	#yuno_ach4::120055	HIDDEN_WARP_NPC,5,5
+yuno_fild04,35,369,0	duplicate(ach_treasure#core)	#yuno_ach5::120056	HIDDEN_WARP_NPC,5,5
+yuno_fild06,262,220,0	duplicate(ach_treasure#core)	#yuno_ach6::120057	HIDDEN_WARP_NPC,5,5
+yuno_fild07,113,339,0	duplicate(ach_treasure#core)	#yuno_ach7::120058	HIDDEN_WARP_NPC,5,5
+yuno_fild08,179,209,0	duplicate(ach_treasure#core)	#yuno_ach8::120059	HIDDEN_WARP_NPC,5,5
+yuno_fild09,166,228,0	duplicate(ach_treasure#core)	#yuno_ach9::120060	HIDDEN_WARP_NPC,5,5
+yuno_fild11,141,357,0	duplicate(ach_treasure#core)	#yuno_ach10::120061	HIDDEN_WARP_NPC,5,5

+ 1 - 0
npc/re/scripts_athena.conf

@@ -99,6 +99,7 @@ npc: npc/re/merchants/shops.txt
 npc: npc/re/merchants/te_merchant.txt
 
 // --------------------------- Others ---------------------------
+npc: npc/re/other/achievements.txt
 npc: npc/re/other/adven_boards.txt
 npc: npc/re/other/bulletin_boards.txt
 npc: npc/re/other/Global_Functions.txt

+ 1 - 0
rAthena.sln

@@ -21,6 +21,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{60D331
 		src\config\const.h = src\config\const.h
 		src\config\core.h = src\config\core.h
 		src\config\classes\general.h = src\config\classes\general.h
+		src\config\packets.h = src\config\packets.h
 		src\config\renewal.h = src\config\renewal.h
 		src\config\secure.h = src\config\secure.h
 	EndProjectSection

+ 9 - 9
sql-files/item_db_re.sql

@@ -1411,7 +1411,7 @@ REPLACE INTO `item_db_re` VALUES (2173,'Crescent_Armguard','Crescent Wrist Guard
 REPLACE INTO `item_db_re` VALUES (2174,'Lumiere_Shield','Lumiere Shield',4,20,NULL,1300,NULL,50,NULL,1,0xFFFFFFFF,63,2,32,NULL,'65',1,3,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2175,'Esprit_Shield','Spirit Shield',4,20,NULL,1300,NULL,50,NULL,1,0xFFFFFFFF,63,2,32,NULL,'65',1,3,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2176,'Dark_Book','Black Book',4,20,NULL,500,NULL,80,NULL,1,0xFFFFFFFF,63,2,32,NULL,'65',1,5,'bonus bMdef,5; .@r = getrefine(); bonus3 bAutoSpellWhenHit,"NPC_DRAGONFEAR",1,(.@r<=6)?(10):((.@r<=8)?(20):(30));',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (2177,'Shield_Of_Death','Shield Of Death',4,20,NULL,2000,NULL,150,NULL,1,0xFFFFFFFF,63,2,32,NULL,'90',1,3,'bonus2 bAddClass,Class_Boss,2; bonus2 bMagicAddClass,Class_Boss,2; bonus2 bAddClass,Class_Normal,10; bonus2 bMagicAddClass,Class_Normal,10;',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (2177,'Shield_Of_Death','Shield Of Death',4,20,NULL,2000,NULL,150,NULL,1,0xFFFFFFFF,63,2,32,NULL,'90',1,3,'bonus2 bAddClass,Class_Boss,2; bonus2 bMagicAddClass,Class_Boss,2; bonus2 bSubClass,Class_Normal,-10;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2178,'TE_Woe_Buckler','TE Woe Buckler',4,0,NULL,0,NULL,15,NULL,0,0xFFFFFFFF,63,2,32,1,'40',1,2,'bonus bMdef,15; bonus bMaxHP,100; bonus bMaxSP,100; bonus2 bSubRace,RC_Player,15;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2179,'TE_Woe_Shield','TE Woe Shield',4,0,NULL,0,NULL,25,NULL,0,0x000444A2,63,2,32,1,'40',1,3,'bonus bMdef,5; bonus bMaxHP,200; bonus2 bSubRace,RC_Player,20;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2180,'TE_Woe_Magic_Guard','TE Woe Magic Guard',4,0,NULL,0,NULL,5,NULL,0,0x00818315,63,2,32,1,'40',1,1,'bonus bMdef,25; bonus bMaxSP,200; bonus2 bSubRace,RC_Player,10;',NULL,NULL);
@@ -7328,8 +7328,8 @@ REPLACE INTO `item_db_re` VALUES (13194,'Peace_Breaker','Peace Breaker',5,195000
 REPLACE INTO `item_db_re` VALUES (13195,'RAG203_','RAG203',5,1800000,NULL,1300,'260',NULL,9,0,0x40000000,63,2,34,3,'140',1,18,'bonus bHit,10; bonus bCriticalRate,15; bonus4 bAutoSpell,"AL_DECAGI",1,10,1;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (13196,'Peace_Breaker_','Peace Breaker',5,1950000,NULL,1400,'250',NULL,9,1,0x41000000,63,2,34,3,'140',1,20,'bonus bHit,-25; bonus bAspdRate,25;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (13197,'Mini_Mei','Mini Mei',5,1600000,NULL,2500,'220',NULL,9,2,0x41000000,63,2,34,2,'106',1,19,NULL,NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (13198,'Tempest_','Tempest',5,2200000,NULL,2500,'250',NULL,9,0,0x41000000,63,2,34,2,'140',1,19,'bonus bHit,-25; bonus bCritical,10; bonus bLongAtkRate,20;',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (13199,'Tempest','Tempest',5,2200000,NULL,2500,'250',NULL,9,1,0x41000000,63,2,34,2,'140',1,19,'bonus bHit,-25; bonus bCritical,10; bonus bLongAtkRate,20;',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (13198,'Tempest_','Tempest',5,2200000,NULL,2500,'250',NULL,9,0,0x41000000,63,2,34,4,'140',1,19,'bonus bHit,-25; bonus bCritical,10; bonus bLongAtkRate,20;',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (13199,'Tempest','Tempest',5,2200000,NULL,2500,'250',NULL,9,1,0x41000000,63,2,34,4,'140',1,19,'bonus bHit,-25; bonus bCritical,10; bonus bLongAtkRate,20;',NULL,NULL);
 #===================================================================
 # Bullets
 #===================================================================
@@ -11110,7 +11110,7 @@ REPLACE INTO `item_db_re` VALUES (22870,'Christmas_Package','Christmas Package',
 REPLACE INTO `item_db_re` VALUES (22873,'Sealed_Beelzebub_Scroll_II','Sealed Beelzebub Scroll II',2,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'getitem callfunc("F_Rand",22875,6238,6239,6228,6232,24231,24232,17474,6635),1;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (22874,'Sealed_Beelzebub_Card_Album','Sealed Beelzebub Card Album',2,10,NULL,50,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'/*No Info*/',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (22875,'Sealed_Beelzebub_Card','Sealed Beelzebub Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,769,NULL,NULL,NULL,NULL,'bonus bVariableCastrate,-15; /*Item removed on 2014-12-17*/',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (22876,'Old_Money_Pocket','Old Money Pocket',3,0,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (22876,'Old_Money_Pocket','Old Money Pocket',3,0,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'Zeny += rand(500,550);',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (22881,'Rope_Gallows','Rope Gallows',2,10,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'/*Used to catch a Lost Sheep*/',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (22882,'Chocolate_Rice_Cake_Soup','Chocolate Rice Cake Soup',2,10,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'percentheal 10,10;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (22883,'September_Gift_Box_','September Gift Box',2,10,NULL,100,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'/*2 Lucky Eggs*/',NULL,NULL);
@@ -11576,13 +11576,13 @@ REPLACE INTO `item_db_re` VALUES (28706,'Dagger_of_Vicious_Mind','Dagger of Vici
 REPLACE INTO `item_db_re` VALUES (28900,'Guardsmen\'s_Shield','Guardsmen\'s Shield',4,20,NULL,3000,NULL,30,NULL,1,0xFFFFFFFF,63,2,32,NULL,'100',1,1,'.@r = getrefine(); skill "LG_SHIELDSPELL",1; bonus3 bAutoSpellWhenHit,"HP_ASSUMPTIO",3,(10+(.@r*10)); bonus bDef,(.@r*10); bonus bMdef,.@r;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (28901,'Cursed_Mad_Bunny','Cursed Mad Bunny',4,20,NULL,100,NULL,0,NULL,0,0xFFFFFFFF,63,2,32,NULL,'1',1,1,'bonus bAspd,3; bonus2 bAddRace,RC_All,5; bonus2 bMagicAddRace,RC_All,5; bonus bShortWeaponDamageReturn,10; autobonus2 "{ bonus bMagicDamageReturn,60; }",10,2000,BF_MAGIC,"{ specialeffect2 EF_WIND; }"; .@r = getrefine(); if(.@r>=7) { bonus bBaseAtk,5; bonus bMatk,5; } if(.@r>=9) { bonus bBaseAtk,15; bonus bMatk,15; } if(.@r>=12) { bonus bCritical,10; bonus bNoCastCancel,0; }',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (28902,'Mad_Bunny_','Mad Bunny',4,20,NULL,100,NULL,0,NULL,1,0xFFFFFFFF,63,2,32,NULL,'1',1,1,'bonus2 bAddRace,RC_All,5; bonus2 bMagicAddRace,RC_All,5; bonus bShortWeaponDamageReturn,10; autobonus2 "{ bonus bMagicDamageReturn,60; }",10,2000,BF_MAGIC,"{ specialeffect2 EF_WIND; }"; .@r = getrefine(); if(.@r>=7) { bonus bBaseAtk,5; bonus bMatk,5; } if(.@r>=9) { bonus bBaseAtk,15; bonus bMatk,15; } if(.@r>=12) { bonus bCritical,10; bonus bNoCastCancel,0; }',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (28903,'Scutum','Scutum',4,0,NULL,500,NULL,1,NULL,1,0xFFFFFFFF,63,2,32,1,'1',1,NULL,'.@r = getrefine(); bonus bFlee,5+(.@r*3); bonus bFlee2,1+(.@r*2); if (.@r > 10) { bonus bMaxHPrate,10; bonus bMaxSPrate,10; }',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (28903,'Scutum','Scutum',4,0,NULL,500,NULL,1,NULL,1,0xFFFFFFFF,63,2,32,NULL,'1',1,1,'.@r = getrefine(); bonus bFlee,5+(.@r*3); bonus bFlee2,1+(.@r*2); if (.@r > 10) { bonus bMaxHPrate,10; bonus bMaxSPrate,10; }',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (28904,'Unity_Guard','Unity Guard',4,20,NULL,300,NULL,60,NULL,1,0xFFFFFFFF,63,2,32,NULL,'100',1,1,'if(BaseLevel<100) { bonus bDef,12*getrefine(); }',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (28905,'Unity_Buckler','Unity Buckler',4,20,NULL,300,NULL,60,NULL,1,0xFFFFFFFF,63,2,32,NULL,'100',1,1,'if(BaseLevel<100) { bonus bMaxSPrate,2*getrefine(); }',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (28906,'Shield_Of_Flame','Shield Of Flame',4,0,NULL,500,NULL,80,NULL,1,0xFFFFFFFF,63,2,32,1,'90',1,NULL,'bonus2 bSubEle,Ele_Fire,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); }',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (28907,'Shield_Of_Gust','Shield Of Gust',4,0,NULL,500,NULL,80,NULL,1,0xFFFFFFFF,63,2,32,1,'90',1,NULL,'bonus2 bSubEle,Ele_Wind,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); }',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (28908,'Shield_Of_Water','Shield Of Water',4,0,NULL,500,NULL,80,NULL,1,0xFFFFFFFF,63,2,32,1,'90',1,NULL,'bonus2 bSubEle,Ele_Water,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); }',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (28909,'Shield_Of_Earth','Shield Of Earth',4,0,NULL,500,NULL,80,NULL,1,0xFFFFFFFF,63,2,32,1,'90',1,NULL,'bonus2 bSubEle,Ele_Earth,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); }',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (28906,'Shield_Of_Flame','Shield Of Flame',4,0,NULL,500,NULL,80,NULL,1,0xFFFFFFFF,63,2,32,NULL,'90',1,1,'bonus2 bSubEle,Ele_Fire,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); }',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (28907,'Shield_Of_Gust','Shield Of Gust',4,0,NULL,500,NULL,80,NULL,1,0xFFFFFFFF,63,2,32,NULL,'90',1,1,'bonus2 bSubEle,Ele_Wind,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); }',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (28908,'Shield_Of_Water','Shield Of Water',4,0,NULL,500,NULL,80,NULL,1,0xFFFFFFFF,63,2,32,NULL,'90',1,1,'bonus2 bSubEle,Ele_Water,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); }',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (28909,'Shield_Of_Earth','Shield Of Earth',4,0,NULL,500,NULL,80,NULL,1,0xFFFFFFFF,63,2,32,NULL,'90',1,1,'bonus2 bSubEle,Ele_Earth,25; .@r = getrefine(); if(.@r > 4) { bonus bAspd,1+((.@r > 6) ? 1 : 0); }',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (28910,'Rectangular_Large_Sleeve','Rectangular Large Sleeve',4,20,NULL,800,NULL,80,NULL,1,0xFFFFFFFF,63,2,32,NULL,'100',1,1,'bonus bLongAtkDef,5; .@r = getrefine(); if(.@r>=5) { bonus bLongAtkDef,5; } if(.@r>=7) { bonus bLongAtkDef,10; } if(.@r>=9) { bonus bLongAtkDef,15; }',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (28913,'Ultralight_Magic_Shield','Ultralight Magic Shield',4,20,NULL,100,NULL,50,NULL,1,0xFFFFFFFF,63,2,32,NULL,'100',1,1,'bonus bAspdRate,5; bonus2 bIgnoreDefClassRate,Class_Normal,10; bonus2 bSubEle,Ele_Neutral,5; .@r = getrefine(); if(.@r>=7) { bonus2 bIgnoreDefClassRate,Class_Normal,2; bonus bAspdRate,2; } if(.@r>=9) { bonus2 bIgnoreDefClassRate,Class_Normal,3; bonus bAspdRate,3; }',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (28915,'Bunker_Shield','Bunker Shield',4,20,NULL,3500,NULL,90,NULL,1,0xFFFFFFFF,63,2,32,NULL,'50',1,1,'bonus2 bAddRace,RC_All,4; bonus bAspdRate,5; .@r = getrefine(); if(.@r>=5) { bonus2 bAddRace,RC_All,.@r; }',NULL,NULL);

+ 24 - 0
sql-files/main.sql

@@ -24,6 +24,29 @@ CREATE TABLE IF NOT EXISTS `acc_reg_str` (
   KEY `account_id` (`account_id`)
 ) ENGINE=MyISAM;
 
+--
+-- Table structure for table `achievement`
+--
+
+CREATE TABLE IF NOT EXISTS `achievement` (
+  `char_id` int(11) unsigned NOT NULL default '0',
+  `id` bigint(11) unsigned NOT NULL,
+  `count1` mediumint(8) unsigned NOT NULL default '0',
+  `count2` mediumint(8) unsigned NOT NULL default '0',
+  `count3` mediumint(8) unsigned NOT NULL default '0',
+  `count4` mediumint(8) unsigned NOT NULL default '0',
+  `count5` mediumint(8) unsigned NOT NULL default '0',
+  `count6` mediumint(8) unsigned NOT NULL default '0',
+  `count7` mediumint(8) unsigned NOT NULL default '0',
+  `count8` mediumint(8) unsigned NOT NULL default '0',
+  `count9` mediumint(8) unsigned NOT NULL default '0',
+  `count10` mediumint(8) unsigned NOT NULL default '0',
+  `completed` datetime,
+  `rewarded` datetime,
+  PRIMARY KEY (`char_id`,`id`),
+  KEY `char_id` (`char_id`)
+) ENGINE=MyISAM;
+
 --
 -- Table structure for table `auction`
 --
@@ -231,6 +254,7 @@ CREATE TABLE IF NOT EXISTS `char` (
   `hotkey_rowshift` tinyint(3) unsigned NOT NULL default '0',
   `clan_id` int(11) unsigned NOT NULL default '0',
   `last_login` datetime DEFAULT NULL,
+  `title_id` INT(11) unsigned NOT NULL default '0',
   PRIMARY KEY  (`char_id`),
   UNIQUE KEY `name_key` (`name`),
   KEY `account_id` (`account_id`),

+ 11 - 1
sql-files/mob_db_re.sql

@@ -3100,7 +3100,17 @@ REPLACE INTO `mob_db_re` VALUES (3508,'DR_EGGRING_G','Eggring','Eggring',20,220,
 #3874,AB_MOB_048
 #3875,AB_MOB_049
 #3876,AB_MOB_050
-
+#3877,E_NYAIL_PIG
+#3878,E_PIT
+#3879,E_SEA_WORMS
+#3880,E_SMALL_SWIRL
+#3881,E_RIPE_WATERMELON
+#3882,E_MD_NYAILO
+#3883,E_MD_NYAILO_LEG
+#3884,E_MD_S_TREASURE_BOX
+#3885,E_MD_B_TREASURE_BOX
+#3886,E_MD_BOX_PUPPET
+#3887,E_MD_DEPRESS_SOUL
 #3888,TW_I_QUEEN_SCARABA
 #3889,TW_GIOIA
 #3890,TW_TIMEHOLDER

+ 0 - 1
sql-files/upgrades/upgrade_20140104.sql

@@ -1 +0,0 @@
-ALTER TABLE  `item_db_re` CHANGE  `atk:matk`  `atk:matk` VARCHAR( 11 ) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL

+ 0 - 20
sql-files/upgrades/upgrade_20140114.sql

@@ -1,20 +0,0 @@
-CREATE TABLE IF NOT EXISTS `vending_items` (
-  `vending_id` int(10) unsigned NOT NULL,
-  `index` smallint(5) unsigned NOT NULL,
-  `cartinventory_id` int(10) unsigned NOT NULL,
-  `amount` smallint(5) unsigned NOT NULL,
-  `price` int(10) unsigned NOT NULL
-) ENGINE=MyISAM;
-
-CREATE TABLE IF NOT EXISTS `vendings` (
-  `id` int(10) unsigned NOT NULL,
-  `account_id` int(11) unsigned NOT NULL,
-  `char_id` int(10) unsigned NOT NULL,
-  `sex` enum('F','M') NOT NULL DEFAULT 'M',
-  `map` varchar(20) NOT NULL,
-  `x` smallint(5) unsigned NOT NULL,
-  `y` smallint(5) unsigned NOT NULL,
-  `title` varchar(80) NOT NULL,
-  `autotrade` tinyint(4) NOT NULL,
-  PRIMARY KEY (`id`)
-) ENGINE=MyISAM;

+ 0 - 21
sql-files/upgrades/upgrade_20140205.sql

@@ -1,21 +0,0 @@
-CREATE TABLE IF NOT EXISTS `buyingstore_items` (
-  `buyingstore_id` int(10) unsigned NOT NULL,
-  `index` smallint(5) unsigned NOT NULL,
-  `item_id` int(10) unsigned NOT NULL,
-  `amount` smallint(5) unsigned NOT NULL,
-  `price` int(10) unsigned NOT NULL
-) ENGINE=MyISAM;
-
-CREATE TABLE IF NOT EXISTS `buyingstores` (
-  `id` int(10) unsigned NOT NULL,
-  `account_id` int(11) unsigned NOT NULL,
-  `char_id` int(10) unsigned NOT NULL,
-  `sex` enum('F','M') NOT NULL DEFAULT 'M',
-  `map` varchar(20) NOT NULL,
-  `x` smallint(5) unsigned NOT NULL,
-  `y` smallint(5) unsigned NOT NULL,
-  `title` varchar(80) NOT NULL,
-  `limit` int(10) unsigned NOT NULL,
-  `autotrade` tinyint(4) NOT NULL,
-  PRIMARY KEY (`id`)
-) ENGINE=MyISAM;

+ 0 - 1
sql-files/upgrades/upgrade_20140523.sql

@@ -1 +0,0 @@
-ALTER TABLE `char` ADD `font` tinyint(3) unsigned NOT NULL default '0';

+ 0 - 118
sql-files/upgrades/upgrade_20140612.sql

@@ -1,118 +0,0 @@
-UPDATE `auction` SET `card0` = 256 WHERE `card0` = -256;
-UPDATE `cart_inventory` SET `card0` = 256 WHERE `card0` = -256;
-UPDATE `guild_storage` SET `card0` = 256 WHERE `card0` = -256;
-UPDATE `inventory` SET `card0` = 256 WHERE `card0` = -256;
-UPDATE `mail` SET `card0` = 256 WHERE `card0` = -256;
-UPDATE `storage` SET `card0` = 256 WHERE `card0` = -256;
-
-UPDATE `auction` SET `card1` = (65536 + `card1`) WHERE `card1` < 0 AND `card0` IN(254,255);
-UPDATE `auction` SET `card2` = (65536 + `card2`) WHERE `card2` < 0 AND `card0` IN(254,255);
-UPDATE `auction` SET `card3` = (65536 + `card3`) WHERE `card3` < 0 AND `card0` IN(254,255);
-
-UPDATE `cart_inventory` SET `card1` = (65536 + `card1`) WHERE `card1` < 0 AND `card0` IN(254,255);
-UPDATE `cart_inventory` SET `card2` = (65536 + `card2`) WHERE `card2` < 0 AND `card0` IN(254,255);
-UPDATE `cart_inventory` SET `card3` = (65536 + `card3`) WHERE `card3` < 0 AND `card0` IN(254,255);
-
-UPDATE `guild_storage` SET `card1` = (65536 + `card1`) WHERE `card1` < 0 AND `card0` IN(254,255);
-UPDATE `guild_storage` SET `card2` = (65536 + `card2`) WHERE `card2` < 0 AND `card0` IN(254,255);
-UPDATE `guild_storage` SET `card3` = (65536 + `card3`) WHERE `card3` < 0 AND `card0` IN(254,255);
-
-UPDATE `inventory` SET `card1` = (65536 + `card1`) WHERE `card1` < 0 AND `card0` IN(254,255);
-UPDATE `inventory` SET `card2` = (65536 + `card2`) WHERE `card2` < 0 AND `card0` IN(254,255);
-UPDATE `inventory` SET `card3` = (65536 + `card3`) WHERE `card3` < 0 AND `card0` IN(254,255);
-
-UPDATE `mail` SET `card1` = (65536 + `card1`) WHERE `card1` < 0 AND `card0` IN(254,255);
-UPDATE `mail` SET `card2` = (65536 + `card2`) WHERE `card2` < 0 AND `card0` IN(254,255);
-UPDATE `mail` SET `card3` = (65536 + `card3`) WHERE `card3` < 0 AND `card0` IN(254,255);
-
-UPDATE `storage` SET `card1` = (65536 + `card1`) WHERE `card1` < 0 AND `card0` IN(254,255);
-UPDATE `storage` SET `card2` = (65536 + `card2`) WHERE `card2` < 0 AND `card0` IN(254,255);
-UPDATE `storage` SET `card3` = (65536 + `card3`) WHERE `card3` < 0 AND `card0` IN(254,255);
-
-ALTER TABLE `auction` MODIFY `nameid` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `auction` MODIFY `card0` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `auction` MODIFY `card1` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `auction` MODIFY `card2` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `auction` MODIFY `card3` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `cart_inventory` MODIFY `nameid` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `cart_inventory` MODIFY `card0` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `cart_inventory` MODIFY `card1` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `cart_inventory` MODIFY `card2` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `cart_inventory` MODIFY `card3` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `guild_storage` MODIFY `nameid` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `guild_storage` MODIFY `card0` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `guild_storage` MODIFY `card1` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `guild_storage` MODIFY `card2` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `guild_storage` MODIFY `card3` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `inventory` MODIFY `nameid` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `inventory` MODIFY `card0` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `inventory` MODIFY `card1` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `inventory` MODIFY `card2` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `inventory` MODIFY `card3` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mail` MODIFY `nameid` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mail` MODIFY `card0` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mail` MODIFY `card1` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mail` MODIFY `card2` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mail` MODIFY `card3` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `pet` MODIFY `egg_id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `storage` MODIFY `nameid` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `storage` MODIFY `card0` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `storage` MODIFY `card1` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `storage` MODIFY `card2` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `storage` MODIFY `card3` smallint(5) unsigned NOT NULL default '0';
-
-ALTER TABLE `mob_db` MODIFY `MVP1id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db` MODIFY `MVP2id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db` MODIFY `MVP3id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db` MODIFY `Drop1id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db` MODIFY `Drop2id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db` MODIFY `Drop3id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db` MODIFY `Drop4id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db` MODIFY `Drop5id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db` MODIFY `Drop6id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db` MODIFY `Drop7id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db` MODIFY `Drop8id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db` MODIFY `Drop9id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db` MODIFY `DropCardid` smallint(5) unsigned NOT NULL default '0';
-
-ALTER TABLE `mob_db2` MODIFY `MVP1id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2` MODIFY `MVP2id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2` MODIFY `MVP3id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2` MODIFY `Drop1id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2` MODIFY `Drop2id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2` MODIFY `Drop3id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2` MODIFY `Drop4id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2` MODIFY `Drop5id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2` MODIFY `Drop6id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2` MODIFY `Drop7id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2` MODIFY `Drop8id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2` MODIFY `Drop9id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2` MODIFY `DropCardid` smallint(5) unsigned NOT NULL default '0';
-
-ALTER TABLE `mob_db2_re` MODIFY `MVP1id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2_re` MODIFY `MVP2id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2_re` MODIFY `MVP3id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2_re` MODIFY `Drop1id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2_re` MODIFY `Drop2id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2_re` MODIFY `Drop3id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2_re` MODIFY `Drop4id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2_re` MODIFY `Drop5id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2_re` MODIFY `Drop6id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2_re` MODIFY `Drop7id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2_re` MODIFY `Drop8id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2_re` MODIFY `Drop9id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db2_re` MODIFY `DropCardid` smallint(5) unsigned NOT NULL default '0';
-
-ALTER TABLE `mob_db_re` MODIFY `MVP1id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db_re` MODIFY `MVP2id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db_re` MODIFY `MVP3id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db_re` MODIFY `Drop1id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db_re` MODIFY `Drop2id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db_re` MODIFY `Drop3id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db_re` MODIFY `Drop4id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db_re` MODIFY `Drop5id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db_re` MODIFY `Drop6id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db_re` MODIFY `Drop7id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db_re` MODIFY `Drop8id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db_re` MODIFY `Drop9id` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mob_db_re` MODIFY `DropCardid` smallint(5) unsigned NOT NULL default '0';

+ 0 - 12
sql-files/upgrades/upgrade_20140612_log.sql

@@ -1,12 +0,0 @@
-UPDATE `picklog` SET `card0` = 256 WHERE `card0` = -256;
-
-UPDATE `picklog` SET `card1` = (65536 + `card1`) WHERE `card1` < 0 AND `card0` IN(254,255);
-UPDATE `picklog` SET `card2` = (65536 + `card2`) WHERE `card2` < 0 AND `card0` IN(254,255);
-UPDATE `picklog` SET `card3` = (65536 + `card3`) WHERE `card3` < 0 AND `card0` IN(254,255);
-
-ALTER TABLE `picklog` MODIFY `nameid` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `picklog` MODIFY `card0` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `picklog` MODIFY `card1` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `picklog` MODIFY `card2` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `picklog` MODIFY `card3` smallint(5) unsigned NOT NULL default '0';
-ALTER TABLE `mvplog` MODIFY `prize` smallint(5) unsigned NOT NULL default '0';

+ 0 - 6
sql-files/upgrades/upgrade_20140616.sql

@@ -1,6 +0,0 @@
-UPDATE `auction` SET `card0` = 256 WHERE `card0` = 65280;
-UPDATE `cart_inventory` SET `card0` = 256 WHERE `card0` = 65280;
-UPDATE `guild_storage` SET `card0` = 256 WHERE `card0` = 65280;
-UPDATE `inventory` SET `card0` = 256 WHERE `card0` = 65280;
-UPDATE `mail` SET `card0` = 256 WHERE `card0` = 65280;
-UPDATE `storage` SET `card0` = 256 WHERE `card0` = 65280;

+ 0 - 1
sql-files/upgrades/upgrade_20140627.sql

@@ -1 +0,0 @@
-ALTER TABLE `pet` CHANGE `incuvate` `incubate` int(11) unsigned NOT NULL default '0';

+ 0 - 1
sql-files/upgrades/upgrade_20140713_log.sql

@@ -1 +0,0 @@
-ALTER TABLE `zenylog` CHANGE `type` `type` ENUM('T','V','P','M','S','N','D','C','A','E','I','B','K') NOT NULL DEFAULT 'S';

+ 0 - 7
sql-files/upgrades/upgrade_20140723.sql

@@ -1,7 +0,0 @@
-ALTER TABLE `vendings` ADD `body_direction` CHAR( 1 ) NOT NULL DEFAULT '4',
-ADD `head_direction` CHAR( 1 ) NOT NULL DEFAULT '0',
-ADD `sit` CHAR( 1 ) NOT NULL DEFAULT '1';
-
-ALTER TABLE `buyingstores` ADD `body_direction` CHAR( 1 ) NOT NULL DEFAULT '4',
-ADD `head_direction` CHAR( 1 ) NOT NULL DEFAULT '0',
-ADD `sit` CHAR( 1 ) NOT NULL DEFAULT '1';

+ 0 - 1
sql-files/upgrades/upgrade_20140822.sql

@@ -1 +0,0 @@
-ALTER TABLE `char` ADD COLUMN `uniqueitem_counter` bigint(20) NOT NULL AFTER `font`;

+ 0 - 1
sql-files/upgrades/upgrade_20140826.sql

@@ -1 +0,0 @@
-ALTER TABLE `char` MODIFY COLUMN `uniqueitem_counter` int(11) unsigned NOT NULL default '0';

+ 0 - 1
sql-files/upgrades/upgrade_20140915.sql

@@ -1 +0,0 @@
-ALTER TABLE `mail` ADD `bound` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0';

+ 0 - 1
sql-files/upgrades/upgrade_20140915_log.sql

@@ -1 +0,0 @@
-ALTER TABLE `picklog` ADD `bound` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0';

+ 0 - 1
sql-files/upgrades/upgrade_20150103_log.sql

@@ -1 +0,0 @@
-ALTER TABLE `picklog` MODIFY `type` ENUM('M','P','L','T','V','S','N','C','A','R','G','E','B','O','I','X','D','U','$') NOT NULL DEFAULT 'S';

+ 0 - 6
sql-files/upgrades/upgrade_20150131.sql

@@ -1,6 +0,0 @@
-ALTER TABLE `bonus_script` MODIFY COLUMN `char_id` INT(11) UNSIGNED NOT NULL;
-ALTER TABLE `bonus_script` MODIFY COLUMN `script` TEXT NOT NULL;
-ALTER TABLE `bonus_script` MODIFY COLUMN `tick` INT(11) UNSIGNED NOT NULL DEFAULT '0';
-ALTER TABLE `bonus_script` MODIFY COLUMN `flag` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0';
-ALTER TABLE `bonus_script` MODIFY COLUMN `type` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0';
-ALTER TABLE `bonus_script` MODIFY COLUMN `icon` SMALLINT(3) NOT NULL DEFAULT '-1';

+ 0 - 6
sql-files/upgrades/upgrade_20150211_skillset.sql

@@ -1,6 +0,0 @@
--- Resetting all `lv` of skills that has `flag` >= 3 (the skill that its `learned_lv` has been changed by script or special case by `learned_lv` + SKILL_FLAG_REPLACED_LV_0)
--- If there's ALL_INCCARRY and ALL_BUYING_STORE, set the `flag` to SKILL_FLAG_PERM_GRANTED (new value is 3), those are exclusive skills given in our official scripts!
-
-UPDATE `skill` SET `lv` = `flag` - 3 WHERE `flag` >= 3;
-UPDATE `skill` SET `flag` = 0 WHERE `flag` >= 3;
-UPDATE `skill` SET `flag` = 3 WHERE `id` = 681 OR `id` = 2535;

+ 0 - 12
sql-files/upgrades/upgrade_20150327_market.sql

@@ -1,12 +0,0 @@
---
--- Table `market` for market shop persistency
---
-
-CREATE TABLE IF NOT EXISTS `market` (
-  `name` varchar(32) NOT NULL DEFAULT '',
-  `nameid` SMALLINT(5) UNSIGNED NOT NULL,
-  `price` INT(11) UNSIGNED NOT NULL,
-  `amount` SMALLINT(5) UNSIGNED NOT NULL,
-  `flag` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0',
-  PRIMARY KEY  (`name`,`nameid`)
-) ENGINE = MyISAM;

+ 0 - 9
sql-files/upgrades/upgrade_20150408.sql

@@ -1,9 +0,0 @@
--- Move `bank_vault` value from `login` to `global_reg_value`.
--- Please be careful if you're running multi char-server, better you do this step manually to move the `bank_vault`
--- to proper `global_reg_value` tables of char-servers used.
-INSERT INTO `global_reg_value` (`char_id`, `str`, `value`, `type`, `account_id`)
-    SELECT '0', '#BANKVAULT', `bank_vault`, '2', `account_id`
-	    FROM `login` WHERE `bank_vault` != 0;
-
--- Remove `bank_vault` from `login` table, login-server side.
-ALTER TABLE `login` DROP `bank_vault`;

+ 0 - 1
sql-files/upgrades/upgrade_20150408_log.sql

@@ -1 +0,0 @@
-ALTER TABLE `picklog` CHANGE `type` `type` ENUM('M','P','L','T','V','S','N','C','A','R','G','E','B','O','I','X','D','U','$','F') NOT NULL DEFAULT 'P';

+ 0 - 68
sql-files/upgrades/upgrade_20150619.sql

@@ -1,68 +0,0 @@
-ALTER TABLE  `char` ADD COLUMN `sex` ENUM('M','F','U') NOT NULL default 'U';
-
---
--- Table structure for `db_roulette`
---
-
-CREATE TABLE `db_roulette` (
-  `index` int(11) NOT NULL default '0',
-  `level` smallint(5) unsigned NOT NULL,
-  `item_id` smallint(5) unsigned NOT NULL,
-  `amount` smallint(5) unsigned NOT NULL DEFAULT '1',
-  `flag` smallint(5) unsigned NOT NULL DEFAULT '1',
-  PRIMARY KEY (`index`)
-) ENGINE=MyISAM;
-
--- ----------------------------
--- Records of db_roulette
--- ----------------------------
--- Info: http://ro.gnjoy.com/news/update/View.asp?seq=157&curpage=1
-
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 0, 1, 675, 1, 1 ); -- Silver_Coin
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 1, 1, 671, 1, 0 ); -- Gold_Coin
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 2, 1, 678, 1, 0 ); -- Poison_Bottle
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 3, 1, 604, 1, 0 ); -- Branch_Of_Dead_Tree
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 4, 1, 522, 1, 0 ); -- Fruit_Of_Mastela
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 5, 1, 671, 1, 0 ); -- Old_Ore_Box
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 6, 1, 12523, 1, 0 ); -- E_Inc_Agi_10_Scroll
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 7, 1, 985, 1, 0 ); -- Elunium
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 8, 1, 984, 1, 0 ); -- Oridecon
-
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 9, 2, 675, 1, 1 ); -- Silver_Coin
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 10, 2, 671, 1, 0 ); -- Gold_Coin
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 11, 2, 603, 1, 0 ); -- Old_Blue_Box
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 12, 2, 608, 1, 0 ); -- Seed_Of_Yggdrasil
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 13, 2, 607, 1, 0 ); -- Yggdrasilberry
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 14, 2, 12522, 1, 0 ); -- E_Blessing_10_Scroll
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 15, 2, 6223, 1, 0 ); -- Carnium
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 16, 2, 6224, 1, 0 ); -- Bradium
-
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 17, 3, 675, 1, 1 ); -- Silver_Coin
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 18, 3, 671, 1, 0 ); -- Gold_Coin
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 19, 3, 12108, 1, 0 ); -- Bundle_Of_Magic_Scroll
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 20, 3, 617, 1, 0 ); -- Old_Violet_Box
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 21, 3, 12514, 1, 0 ); -- E_Abrasive
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 22, 3, 7444, 1, 0 ); -- Treasure_Box
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 23, 3, 969, 1, 0 ); -- Gold
-
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 24, 4, 675, 1, 1 ); -- Silver_Coin
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 25, 4, 671, 1, 0 ); -- Gold_Coin
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 26, 4, 616, 1, 0 ); -- Old_Card_Album
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 27, 4, 12516, 1, 0 ); -- E_Small_Life_Potion
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 28, 4, 22777, 1, 0 ); -- Gift_Buff_Set
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 29, 4, 6231, 1, 0 ); -- Guarantee_Weapon_6Up
-
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 30, 5, 671, 1, 1 ); -- Gold_Coin
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 31, 5, 12246, 1, 0 ); -- Magic_Card_Album
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 32, 5, 12263, 1, 0 ); -- Comp_Battle_Manual
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 33, 5, 671, 1, 0 ); -- Potion_Box
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 34, 5, 6235, 1, 0 ); -- Guarantee_Armor_6Up
-
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 35, 6, 671, 1, 1 ); -- Gold_Coin
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 36, 6, 12766, 1, 0 ); -- Reward_Job_BM25
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 37, 6, 6234, 1, 0 ); -- Guarantee_Armor_7Up
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 38, 6, 6233, 1, 0 ); -- Guarantee_Armor_8Up
-
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 39, 7, 671, 1, 1 ); -- Gold_Coin
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 40, 7, 6233, 1, 0 ); -- Guarantee_Armor_8Up
-INSERT INTO `db_roulette`(`index`, `level`, `item_id`, `amount`, `flag` ) VALUES ( 41, 7, 6233, 1, 0 ); -- Guarantee_Armor_8Up	// KRO lists this twice

+ 0 - 1
sql-files/upgrades/upgrade_20150619_log.sql

@@ -1 +0,0 @@
-ALTER TABLE `picklog` MODIFY `type` enum('M','P','L','T','V','S','N','C','A','R','G','E','B','O','I','X','D','U','$','F','Y') NOT NULL default 'P';

+ 0 - 1
sql-files/upgrades/upgrade_20150804_log.sql

@@ -1 +0,0 @@
-ALTER TABLE `picklog` CHANGE `type` `type` ENUM('M','P','L','T','V','S','N','C','A','R','G','E','B','O','I','X','D','U','$','F','Z') NOT NULL DEFAULT 'P';

+ 0 - 1
sql-files/upgrades/upgrade_20150828.sql

@@ -1 +0,0 @@
-ALTER TABLE `char` ADD COLUMN `hotkey_rowshift` TINYINT(3) UNSIGNED NOT NULL DEFAULT  '0';

+ 0 - 66
sql-files/upgrades/upgrade_20150831.sql

@@ -1,66 +0,0 @@
-ALTER TABLE `mapreg` ADD PRIMARY KEY (`varname`, `index`);
-ALTER TABLE `mapreg` DROP INDEX `varname`;
-ALTER TABLE `mapreg` DROP INDEX `index`;
-ALTER TABLE `mapreg` MODIFY `varname` varchar(32) binary NOT NULL;
-
-CREATE TABLE IF NOT EXISTS `acc_reg_num` (
-  `account_id` int(11) unsigned NOT NULL default '0',
-  `key` varchar(32) binary NOT NULL default '',
-  `index` int(11) unsigned NOT NULL default '0',
-  `value` int(11) NOT NULL default '0',
-  PRIMARY KEY (`account_id`,`key`,`index`),
-  KEY `account_id` (`account_id`)
-) ENGINE=MyISAM;
-
-CREATE TABLE IF NOT EXISTS `acc_reg_str` (
-  `account_id` int(11) unsigned NOT NULL default '0',
-  `key` varchar(32) binary NOT NULL default '',
-  `index` int(11) unsigned NOT NULL default '0',
-  `value` varchar(254) NOT NULL default '0',
-  PRIMARY KEY (`account_id`,`key`,`index`),
-  KEY `account_id` (`account_id`)
-) ENGINE=MyISAM;
-
-CREATE TABLE IF NOT EXISTS `char_reg_num` (
-  `char_id` int(11) unsigned NOT NULL default '0',
-  `key` varchar(32) binary NOT NULL default '',
-  `index` int(11) unsigned NOT NULL default '0',
-  `value` int(11) NOT NULL default '0',
-  PRIMARY KEY (`char_id`,`key`,`index`),
-  KEY `char_id` (`char_id`)
-) ENGINE=MyISAM;
-
-CREATE TABLE IF NOT EXISTS `char_reg_str` (
-  `char_id` int(11) unsigned NOT NULL default '0',
-  `key` varchar(32) binary NOT NULL default '',
-  `index` int(11) unsigned NOT NULL default '0',
-  `value` varchar(254) NOT NULL default '0',
-  PRIMARY KEY (`char_id`,`key`,`index`),
-  KEY `char_id` (`char_id`)
-) ENGINE=MyISAM;
-
-CREATE TABLE IF NOT EXISTS `global_acc_reg_num` (
-  `account_id` int(11) unsigned NOT NULL default '0',
-  `key` varchar(32) binary NOT NULL default '',
-  `index` int(11) unsigned NOT NULL default '0',
-  `value` int(11) NOT NULL default '0',
-  PRIMARY KEY (`account_id`,`key`,`index`),
-  KEY `account_id` (`account_id`)
-) ENGINE=MyISAM;
-
-CREATE TABLE IF NOT EXISTS `global_acc_reg_str` (
-  `account_id` int(11) unsigned NOT NULL default '0',
-  `key` varchar(32) binary NOT NULL default '',
-  `index` int(11) unsigned NOT NULL default '0',
-  `value` varchar(254) NOT NULL default '0',
-  PRIMARY KEY (`account_id`,`key`,`index`),
-  KEY `account_id` (`account_id`)
-) ENGINE=MyISAM;
-
-INSERT INTO `acc_reg_num` (`account_id`, `key`, `index`, `value`) SELECT `account_id`, `str`, 0, `value` FROM `global_reg_value` WHERE `type` = 2 AND `str` NOT LIKE '%$';
-INSERT INTO `acc_reg_str` (`account_id`, `key`, `index`, `value`) SELECT `account_id`, `str`, 0, `value` FROM `global_reg_value` WHERE `type` = 2 AND `str` LIKE '%$';
-INSERT INTO `char_reg_num` (`char_id`, `key`, `index`, `value`) SELECT `char_id`, `str`, 0, `value` FROM `global_reg_value` WHERE `type` = 3 AND `str` NOT LIKE '%$';
-INSERT INTO `char_reg_str` (`char_id`, `key`, `index`, `value`) SELECT `char_id`, `str`, 0, `value` FROM `global_reg_value` WHERE `type` = 3 AND `str` LIKE '%$';
-INSERT INTO `global_acc_reg_num` (`account_id`, `key`, `index`, `value`) SELECT `account_id`, `str`, 0, `value` FROM `global_reg_value` WHERE `type` = 1 AND `str` NOT LIKE '%$';
-INSERT INTO `global_acc_reg_str` (`account_id`, `key`, `index`, `value`) SELECT `account_id`, `str`, 0, `value` FROM `global_reg_value` WHERE `type` = 1 AND `str` LIKE '%$';
-# DROP TABLE `global_reg_value`;

+ 0 - 1
sql-files/upgrades/upgrade_20150917_log.sql

@@ -1 +0,0 @@
-ALTER TABLE `picklog` MODIFY `type` enum('M','P','L','T','V','S','N','C','A','R','G','E','B','O','I','X','D','U','$','F','Z','Q') NOT NULL default 'P';

+ 0 - 19
sql-files/upgrades/upgrade_20151230_log.sql

@@ -1,19 +0,0 @@
---
--- Table structure for table `feedinglog`
---
-
-CREATE TABLE IF NOT EXISTS `feedinglog` (
-  `id` INT(11) NOT NULL AUTO_INCREMENT,
-  `time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
-  `char_id` INT(11) NOT NULL,
-  `target_id` INT(11) NOT NULL,
-  `target_class` SMALLINT(11) NOT NULL,
-  `type` ENUM('P','H','O') NOT NULL, -- P: Pet, H: Homunculus, O: Other
-  `intimacy` INT(11) UNSIGNED NOT NULL,
-  `item_id` SMALLINT(5) UNSIGNED NOT NULL,
-  `map` VARCHAR(11) NOT NULL,
-  `x` SMALLINT(5) UNSIGNED NOT NULL,
-  `y` SMALLINT(5) UNSIGNED NOT NULL,
-  PRIMARY KEY  (`id`)
-) ENGINE = MyISAM AUTO_INCREMENT = 1;
-

+ 25 - 0
sql-files/upgrades/upgrade_20170407.sql

@@ -0,0 +1,25 @@
+ALTER TABLE `char`
+	ADD COLUMN `title_id` int(11) unsigned NOT NULL default '0' AFTER `clan_id`;
+
+--
+-- Table structure for table `achievement`
+--
+
+CREATE TABLE IF NOT EXISTS `achievement` (
+  `char_id` int(11) unsigned NOT NULL default '0',
+  `id` bigint(11) unsigned NOT NULL,
+  `count1` mediumint(8) unsigned NOT NULL default '0',
+  `count2` mediumint(8) unsigned NOT NULL default '0',
+  `count3` mediumint(8) unsigned NOT NULL default '0',
+  `count4` mediumint(8) unsigned NOT NULL default '0',
+  `count5` mediumint(8) unsigned NOT NULL default '0',
+  `count6` mediumint(8) unsigned NOT NULL default '0',
+  `count7` mediumint(8) unsigned NOT NULL default '0',
+  `count8` mediumint(8) unsigned NOT NULL default '0',
+  `count9` mediumint(8) unsigned NOT NULL default '0',
+  `count10` mediumint(8) unsigned NOT NULL default '0',
+  `completed` datetime,
+  `rewarded` datetime,
+  PRIMARY KEY (`char_id`,`id`),
+  KEY `char_id` (`char_id`)
+) ENGINE=MyISAM;

+ 2 - 0
src/char/char-server.vcxproj

@@ -161,6 +161,7 @@
     <ClInclude Include="char_logif.h" />
     <ClInclude Include="char_mapif.h" />
     <ClInclude Include="inter.h" />
+    <ClInclude Include="int_achievement.h" />
     <ClInclude Include="int_auction.h" />
     <ClInclude Include="int_clan.h" />
     <ClInclude Include="int_elemental.h" />
@@ -182,6 +183,7 @@
     <ClCompile Include="char_logif.c" />
     <ClCompile Include="char_mapif.c" />
     <ClCompile Include="inter.c" />
+    <ClCompile Include="int_achievement.c" />
     <ClCompile Include="int_auction.c" />
     <ClCompile Include="int_clan.c" />
     <ClCompile Include="int_elemental.c" />

+ 6 - 0
src/char/char-server.vcxproj.filters

@@ -26,6 +26,9 @@
     <ClInclude Include="char_mapif.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="int_achievement.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="int_auction.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -79,6 +82,9 @@
     <ClCompile Include="char_mapif.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="int_achievement.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="int_auction.c">
       <Filter>Source Files</Filter>
     </ClCompile>

+ 23 - 8
src/char/char.cpp

@@ -300,7 +300,7 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){
 		(p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date) ||
 		(p->rename != cp->rename) || (p->robe != cp->robe) || (p->character_moves != cp->character_moves) ||
 		(p->unban_time != cp->unban_time) || (p->font != cp->font) || (p->uniqueitem_counter != cp->uniqueitem_counter) ||
-		(p->hotkey_rowshift != cp->hotkey_rowshift) || (p->clan_id != cp->clan_id )
+		(p->hotkey_rowshift != cp->hotkey_rowshift) || (p->clan_id != cp->clan_id ) || (p->title_id != cp->title_id)
 	)
 	{	//Save status
 		if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d',"
@@ -311,7 +311,7 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){
 			"`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d',"
 			"`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d',"
 			"`delete_date`='%lu',`robe`='%d',`moves`='%d',`font`='%u',`uniqueitem_counter`='%u',"
-			"`hotkey_rowshift`='%d', `clan_id`='%d'"
+			"`hotkey_rowshift`='%d', `clan_id`='%d', `title_id`='%lu'"
 			" WHERE `account_id`='%d' AND `char_id` = '%d'",
 			schema_config.char_db, p->base_level, p->job_level,
 			p->base_exp, p->job_exp, p->zeny,
@@ -323,7 +323,7 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){
 			mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename,
 			(unsigned long)p->delete_date, // FIXME: platform-dependent size
 			p->robe, p->character_moves, p->font, p->uniqueitem_counter,
-			p->hotkey_rowshift, p->clan_id,
+			p->hotkey_rowshift, p->clan_id, p->title_id,
 			p->account_id, p->char_id) )
 		{
 			Sql_ShowDebug(sql_handle);
@@ -917,7 +917,7 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) {
 		"`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`,"
 		"`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`,"
 		"`clothes_color`,`body`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`,"
-		"`robe`,`moves`,`unban_time`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`"
+		"`robe`,`moves`,`unban_time`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`,`title_id`"
 		" FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", schema_config.char_db, sd->account_id, MAX_CHARS)
 	||	SQL_ERROR == SqlStmt_Execute(stmt)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 0,  SQLDT_INT,    &p.char_id, 0, NULL, NULL)
@@ -963,6 +963,7 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) {
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 40, SQLDT_UINT,   &p.uniqueitem_counter, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 41, SQLDT_ENUM,   &sex, sizeof(sex), NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 42, SQLDT_UCHAR,   &p.hotkey_rowshift, 0, NULL, NULL)
+	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 43, SQLDT_ULONG,	&p.title_id, 0, NULL, NULL)
 	)
 	{
 		SqlStmt_ShowDebug(stmt);
@@ -1026,7 +1027,7 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev
 		"`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`,"
 		"`hair_color`,`clothes_color`,`body`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`,"
 		"`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`, `moves`,"
-		"`unban_time`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`,`clan_id`"
+		"`unban_time`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`,`clan_id`,`title_id`"
 		" FROM `%s` WHERE `char_id`=? LIMIT 1", schema_config.char_db)
 	||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
 	||	SQL_ERROR == SqlStmt_Execute(stmt)
@@ -1090,6 +1091,7 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 57, SQLDT_ENUM,   &sex, sizeof(sex), NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 58, SQLDT_UCHAR,  &p->hotkey_rowshift, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 59, SQLDT_INT,    &p->clan_id, 0, NULL, NULL)
+	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 60, SQLDT_ULONG,	&p->title_id, 0, NULL, NULL)
 	)
 	{
 		SqlStmt_ShowDebug(stmt);
@@ -1671,6 +1673,10 @@ int char_delete_char_sql(uint32 char_id){
 	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", schema_config.bonus_script_db, char_id) )
 		Sql_ShowDebug(sql_handle);
 
+	/* Achievement Data */
+	if (SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", schema_config.achievement_table, char_id))
+		Sql_ShowDebug(sql_handle);
+
 	if (charserv_config.log_char) {
 		if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`char_msg`,`name`) VALUES (NOW(), '%d', '%d', 'Deleted char (CID %d)', '%s')",
 			schema_config.charlog_db, account_id, 0, char_id, esc_name) )
@@ -2236,7 +2242,7 @@ bool char_checkdb(void){
                 schema_config.auction_db, schema_config.quest_db, schema_config.homunculus_db, schema_config.skill_homunculus_db,
                 schema_config.mercenary_db, schema_config.mercenary_owner_db,
 		schema_config.elemental_db, schema_config.ragsrvinfo_db, schema_config.skillcooldown_db, schema_config.bonus_script_db,
-		schema_config.clan_table, schema_config.clan_alliance_table, schema_config.mail_attachment_db
+		schema_config.clan_table, schema_config.clan_alliance_table, schema_config.mail_attachment_db, schema_config.achievement_table
 	};
 	ShowInfo("Start checking DB integrity\n");
 	for (i=0; i<ARRAYLENGTH(sqltable); i++){ //check if they all exist and we can acces them in sql-server
@@ -2252,7 +2258,7 @@ bool char_checkdb(void){
 		"`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`,`hair_color`,`clothes_color`,`weapon`,"
 		"`shield`,`head_top`,`head_mid`,`head_bottom`,`robe`,`last_map`,`last_x`,`last_y`,`save_map`,"
 		"`save_x`,`save_y`,`partner_id`,`online`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,"
-		"`moves`,`unban_time`,`font`,`sex`,`hotkey_rowshift`,`clan_id`,`last_login`"
+		"`moves`,`unban_time`,`font`,`sex`,`hotkey_rowshift`,`clan_id`,`last_login`,`title_id`"
 		" FROM `%s` LIMIT 1;", schema_config.char_db) ){
 		Sql_ShowDebug(sql_handle);
 		return false;
@@ -2314,7 +2320,7 @@ bool char_checkdb(void){
 	//checking guild_db
 	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT  `guild_id`,`name`,`char_id`,`master`,`guild_lv`,"
 			"`connect_member`,`max_member`,`average_lv`,`exp`,`next_exp`,`skill_point`,`mes1`,`mes2`,"
-			"`emblem_len`,`emblem_id`,`emblem_data`"
+			"`emblem_len`,`emblem_id`,`emblem_data`,`last_master_change`"
 			" FROM `%s` LIMIT 1;", schema_config.guild_db) ){
 		Sql_ShowDebug(sql_handle);
 		return false;
@@ -2478,6 +2484,12 @@ bool char_checkdb(void){
 		Sql_ShowDebug(sql_handle);
 		return false;
 	}
+	//checking achievement_table
+	if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`id`,`count1`,`count2`,`count3`,`count4`,`count5`,`count6`,`count7`,`count8`,`count9`,`count10`,`completed`,`rewarded`"
+		" FROM `%s` LIMIT 1;", schema_config.achievement_table)) {
+		Sql_ShowDebug(sql_handle);
+		return false;
+	}
 	Sql_FreeResult(sql_handle);
 	ShowInfo("DB integrity check finished with success\n");
 	return true;
@@ -2573,6 +2585,8 @@ void char_sql_config_read(const char* cfgName) {
 			safestrncpy(schema_config.clan_table, w2, sizeof(schema_config.clan_table));
 		else if(!strcmpi(w1,"clan_alliance_table"))
 			safestrncpy(schema_config.clan_alliance_table, w2, sizeof(schema_config.clan_alliance_table));
+		else if(!strcmpi(w1,"achievement_table"))
+			safestrncpy(schema_config.achievement_table, w2, sizeof(schema_config.achievement_table));
 		//support the import command, just like any other config
 		else if(!strcmpi(w1,"import"))
 			char_sql_config_read(w2);
@@ -2622,6 +2636,7 @@ void char_set_default_sql(){
 	safestrncpy(schema_config.acc_reg_num_table,"acc_reg_num",sizeof(schema_config.acc_reg_num_table));
 	safestrncpy(schema_config.clan_table,"clan",sizeof(schema_config.clan_table));
 	safestrncpy(schema_config.clan_table,"clan_alliance",sizeof(schema_config.clan_alliance_table));
+	safestrncpy(schema_config.achievement_table,"achievement",sizeof(schema_config.achievement_table));
 }
 
 //set default config

+ 1 - 1
src/char/char.h

@@ -80,6 +80,7 @@ struct Schema_Config {
 	char char_reg_num_table[DB_NAME_LEN];
 	char clan_table[DB_NAME_LEN];
 	char clan_alliance_table[DB_NAME_LEN];
+	char achievement_table[DB_NAME_LEN];
 };
 extern struct Schema_Config schema_config;
 
@@ -222,7 +223,6 @@ struct char_session_data {
 	uint8 char_slots; // total number of characters that can be created
 	uint8 chars_vip;
 	uint8 chars_billing;
-	uint32 version;
 	uint8 clienttype;
 	char new_name[NAME_LENGTH];
 	char birthdate[10+1];  // YYYY-MM-DD

+ 25 - 24
src/char/char_clif.c

@@ -303,8 +303,7 @@ int chclif_parse_pincode_setnew( int fd, struct char_session_data* sd ){
 //----------------------------------------
 void chclif_charlist_notify( int fd, struct char_session_data* sd ){
 // This is needed on RE clients from october 2015 onwards
-// If you want to use one replace false by true here
-#if false && PACKETVER >= 20151001
+#if defined(PACKETVER_RE) && PACKETVER >= 20151001
 	WFIFOHEAD(fd, 10);
 	WFIFOW(fd, 0) = 0x9a0;
 	// pages to req / send them all in 1 until mmo_chars_fromsql can split them up
@@ -324,21 +323,25 @@ void chclif_charlist_notify( int fd, struct char_session_data* sd ){
 // Function to send characters to a player
 //----------------------------------------
 int chclif_mmo_send006b(int fd, struct char_session_data* sd){
-	int j, offset = 0;
-	bool newvers = (sd->version >= date2version(20100413) );
-	if(newvers) //20100413
-		offset += 3;
+	int j, offset;
+
+#if PACKETVER >= 20100413
+	offset = 3;
+#else
+	offset = 0;
+#endif
+
 	if (charserv_config.save_log)
 		ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id);
 
 	j = 24 + offset; // offset
 	WFIFOHEAD(fd,j + MAX_CHARS*MAX_CHAR_BUF);
 	WFIFOW(fd,0) = 0x6b;
-	if(newvers){ //20100413
+#if PACKETVER >= 20100413
 		WFIFOB(fd,4) = MAX_CHARS; // Max slots.
 		WFIFOB(fd,5) = MIN_CHARS; // Available slots. (PremiumStartSlot)
 		WFIFOB(fd,6) = MIN_CHARS+sd->chars_vip; // Premium slots. (Any existent chars past sd->char_slots but within MAX_CHARS will show a 'Premium Service' in red)
-	}
+#endif
 	memset(WFIFOP(fd,4 + offset), 0, 20); // unknown bytes
 	j+=char_mmo_chars_fromsql(sd, WFIFOP(fd,j));
 	WFIFOW(fd,2) = j; // packet len
@@ -377,16 +380,18 @@ void chclif_mmo_send099d(int fd, struct char_session_data *sd) {
  * Function to choose wich kind of charlist to send to client depending on his version
  */
 void chclif_mmo_char_send(int fd, struct char_session_data* sd){
-	ShowInfo("sd->version = %d\n",sd->version);
-	if(sd->version >= date2version(20130000) ){
-		chclif_mmo_send082d(fd,sd);
-		chclif_mmo_send006b(fd,sd);
-		chclif_charlist_notify(fd,sd);
-	} else
-		chclif_mmo_send006b(fd,sd);
+#if PACKETVER >= 20130000
+	chclif_mmo_send082d(fd, sd);
+	chclif_mmo_send006b(fd, sd);
+	chclif_charlist_notify(fd, sd);
+#else
+	chclif_mmo_send006b(fd,sd);
 	//@FIXME dump from kro doesn't show 6b transmission
-	if(sd->version >= date2version(20060819) )
- 		chclif_block_character(fd,sd);
+#endif
+
+#if PACKETVER >= 20060819
+ 	chclif_block_character(fd,sd);
+#endif
 }
 
 /*
@@ -435,14 +440,11 @@ void chclif_char_delete2_ack(int fd, uint32 char_id, uint32 result, time_t delet
 /// Any (0x718): An unknown error has occurred.
 /// HC: <082a>.W <char id>.L <Msg:0-5>.L
 void chclif_char_delete2_accept_ack(int fd, uint32 char_id, uint32 result) {
+#if PACKETVER >= 20130000
 	if(result == 1 ){
-		struct char_session_data* sd;
-		sd = (struct char_session_data*)session[fd]->session_data;
-
-		if( sd->version >= date2version(20130000) ){
-			chclif_mmo_char_send(fd, sd);
-		}
+		chclif_mmo_char_send(fd, session[fd]->session_data);
 	}
+#endif
 
 	WFIFOHEAD(fd,10);
 	WFIFOW(fd,0) = 0x82a;
@@ -751,7 +753,6 @@ int chclif_parse_reqtoconnect(int fd, struct char_session_data* sd,uint32 ipl){
 			node->login_id2  == login_id2 /*&&
 			node->ip         == ipl*/ )
 		{// authentication found (coming from map server)
-			sd->version = node->version;
 			idb_remove(auth_db, account_id);
 			char_auth_ok(fd, sd);
 		}

+ 4 - 10
src/char/char_logif.c

@@ -295,7 +295,7 @@ int chlogif_parse_ackconnect(int fd, struct char_session_data* sd){
 }
 
 int chlogif_parse_ackaccreq(int fd, struct char_session_data* sd){
-	if (RFIFOREST(fd) < 25)
+	if (RFIFOREST(fd) < 21)
 		return 0;
 	{
 		uint32 account_id = RFIFOL(fd,2);
@@ -304,19 +304,14 @@ int chlogif_parse_ackaccreq(int fd, struct char_session_data* sd){
 		uint8 sex = RFIFOB(fd,14);
 		uint8 result = RFIFOB(fd,15);
 		int request_id = RFIFOL(fd,16);
-		uint32 version = RFIFOL(fd,20);
-		uint8 clienttype = RFIFOB(fd,24);
-		RFIFOSKIP(fd,25);
+		uint8 clienttype = RFIFOB(fd,20);
+		RFIFOSKIP(fd,21);
 
 		if( session_isActive(request_id) && (sd=(struct char_session_data*)session[request_id]->session_data) &&
 			!sd->auth && sd->account_id == account_id && sd->login_id1 == login_id1 && sd->login_id2 == login_id2 && sd->sex == sex )
 		{
 			int client_fd = request_id;
-			sd->version = version;
 			sd->clienttype = clienttype;
-			if(sd->version != date2version(PACKETVER))
-				ShowWarning("aid=%d has an incorect version=%d in clientinfo. Server compiled for %d\n",
-					sd->account_id,sd->version,date2version(PACKETVER));
 
 			switch( result )
 			{
@@ -372,8 +367,7 @@ int chlogif_parse_reqaccdata(int fd, struct char_session_data* sd){
 			// send characters to player
 			chclif_mmo_char_send(u_fd, sd);
 #if PACKETVER_SUPPORTS_PINCODE
-			if(sd->version >= date2version(20110309))
-				chlogif_pincode_start(u_fd,sd);
+			chlogif_pincode_start(u_fd,sd);
 #endif
 		}
 	}

+ 2 - 4
src/char/char_mapif.c

@@ -453,15 +453,14 @@ void chmapif_charselres(int fd, uint32 aid, uint8 res){
  * @return : 0 not enough data received, 1 success
  */
 int chmapif_parse_authok(int fd){
-	if( RFIFOREST(fd) < 19 )
+	if( RFIFOREST(fd) < 18 )
 		return 0;
 	else{
 		uint32 account_id = RFIFOL(fd,2);
 		uint32 login_id1 = RFIFOL(fd,6);
 		uint32 login_id2 = RFIFOL(fd,10);
 		uint32 ip = RFIFOL(fd,14);
-		int version = RFIFOB(fd,18);
-		RFIFOSKIP(fd,19);
+		RFIFOSKIP(fd,18);
 
 		if( runflag != CHARSERVER_ST_RUNNING ){
 			chmapif_charselres(fd,account_id,0);
@@ -478,7 +477,6 @@ int chmapif_parse_authok(int fd){
 			node->login_id2 = login_id2;
 			//node->sex = 0;
 			node->ip = ntohl(ip);
-			node->version = version; //upd version for mapserv
 			//node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server)
 			//node->gmlevel = 0;
 			idb_put(auth_db, account_id, node);

+ 344 - 0
src/char/int_achievement.c

@@ -0,0 +1,344 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/db.h"
+#include "../common/malloc.h"
+#include "../common/mmo.h"
+#include "../common/socket.h"
+#include "../common/sql.h"
+#include "../common/strlib.h"
+
+#include "char.h"
+#include "inter.h"
+#include "int_achievement.h"
+#include "int_mail.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/**
+ * Load achievements for a character.
+ * @param char_id: Character ID
+ * @param count: Pointer to return the number of found entries.
+ * @return Array of found entries. It has *count entries, and it is care of the caller to aFree() it afterwards.
+ */
+struct achievement *mapif_achievements_fromsql(uint32 char_id, int *count)
+{
+	struct achievement *achievelog = NULL;
+	struct achievement tmp_achieve;
+	SqlStmt *stmt;
+	StringBuf buf;
+	int i;
+
+	if (!count)
+		return NULL;
+
+	memset(&tmp_achieve, 0, sizeof(tmp_achieve));
+
+	StringBuf_Init(&buf);
+	StringBuf_AppendStr(&buf, "SELECT `id`, COALESCE(UNIX_TIMESTAMP(`completed`),0), COALESCE(UNIX_TIMESTAMP(`rewarded`),0)");
+	for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; ++i)
+		StringBuf_Printf(&buf, ", `count%d`", i + 1);
+	StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id` = '%u'", schema_config.achievement_table, char_id);
+
+	stmt = SqlStmt_Malloc(sql_handle);
+	if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf))
+	||  SQL_ERROR == SqlStmt_Execute(stmt) )
+	{
+		SqlStmt_ShowDebug(stmt);
+		SqlStmt_Free(stmt);
+		StringBuf_Destroy(&buf);
+		*count = 0;
+		return NULL;
+	}
+
+	SqlStmt_BindColumn(stmt, 0, SQLDT_INT,  &tmp_achieve.achievement_id, 0, NULL, NULL);
+	SqlStmt_BindColumn(stmt, 1, SQLDT_INT,  &tmp_achieve.completed, 0, NULL, NULL);
+	SqlStmt_BindColumn(stmt, 2, SQLDT_INT,  &tmp_achieve.rewarded, 0, NULL, NULL);
+	for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; ++i)
+		SqlStmt_BindColumn(stmt, 3 + i, SQLDT_INT, &tmp_achieve.count[i], 0, NULL, NULL);
+
+	*count = (int)SqlStmt_NumRows(stmt);
+	if (*count > 0) {
+		i = 0;
+
+		achievelog = (struct achievement *)aCalloc(*count, sizeof(struct achievement));
+		while (SQL_SUCCESS == SqlStmt_NextRow(stmt)) {
+			if (i >= *count) // Sanity check, should never happen
+				break;
+			memcpy(&achievelog[i++], &tmp_achieve, sizeof(tmp_achieve));
+		}
+		if (i < *count) {
+			// Should never happen. Compact array
+			*count = i;
+			achievelog = (struct achievement *)aRealloc(achievelog, sizeof(struct achievement) * i);
+		}
+	}
+
+	SqlStmt_Free(stmt);
+	StringBuf_Clear(&buf);
+	return achievelog;
+}
+
+/**
+ * Deletes an achievement from a character's achievementlog.
+ * @param char_id: Character ID
+ * @param achievement_id: Achievement ID
+ * @return false in case of errors, true otherwise
+ */
+bool mapif_achievement_delete(uint32 char_id, int achievement_id)
+{
+	if (SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d' AND `char_id` = '%u'", schema_config.achievement_table, achievement_id, char_id)) {
+		Sql_ShowDebug(sql_handle);
+		return false;
+	}
+
+	return true;
+}
+
+/**
+ * Adds an achievement to a character's achievementlog.
+ * @param char_id: Character ID
+ * @param ad: Achievement data
+ * @return false in case of errors, true otherwise
+ */
+bool mapif_achievement_add(uint32 char_id, struct achievement ad)
+{
+	StringBuf buf;
+	int i;
+
+	StringBuf_Init(&buf);
+	StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `id`, `completed`, `rewarded`", schema_config.achievement_table);
+	for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; ++i)
+		StringBuf_Printf(&buf, ", `count%d`", i + 1);
+	StringBuf_AppendStr(&buf, ")");
+	StringBuf_Printf(&buf, " VALUES ('%u', '%d',", char_id, ad.achievement_id, (uint32)ad.completed, (uint32)ad.rewarded);
+	if( ad.completed ){
+		StringBuf_Printf(&buf, "FROM_UNIXTIME('%u'),", (uint32)ad.completed);
+	}else{
+		StringBuf_AppendStr(&buf, "NULL,");
+	}
+	if( ad.rewarded ){
+		StringBuf_Printf(&buf, "FROM_UNIXTIME('%u')", (uint32)ad.rewarded);
+	}else{
+		StringBuf_AppendStr(&buf, "NULL");
+	}
+	for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; ++i)
+		StringBuf_Printf(&buf, ", '%d'", ad.count[i]);
+	StringBuf_AppendStr(&buf, ")");
+
+	if (SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf))) {
+		Sql_ShowDebug(sql_handle);
+		StringBuf_Clear(&buf);
+		return false;
+	}
+
+	StringBuf_Clear(&buf);
+
+	return true;
+}
+
+/**
+ * Updates an achievement in a character's achievementlog.
+ * @param char_id: Character ID
+ * @param ad: Achievement data
+ * @return false in case of errors, true otherwise
+ */
+bool mapif_achievement_update(uint32 char_id, struct achievement ad)
+{
+	StringBuf buf;
+	int i;
+
+	StringBuf_Init(&buf);
+	StringBuf_Printf(&buf, "UPDATE `%s` SET ", schema_config.achievement_table);
+	if( ad.completed ){
+		StringBuf_Printf(&buf, "`completed` = FROM_UNIXTIME('%u'),", (uint32)ad.completed);
+	}else{
+		StringBuf_AppendStr(&buf, "`completed` = NULL,");
+	}
+	if( ad.rewarded ){
+		StringBuf_Printf(&buf, "`rewarded` = FROM_UNIXTIME('%u')", (uint32)ad.rewarded);
+	}else{
+		StringBuf_AppendStr(&buf, "`rewarded` = NULL");
+	}
+	for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; ++i)
+		StringBuf_Printf(&buf, ", `count%d` = '%d'", i + 1, ad.count[i]);
+	StringBuf_Printf(&buf, " WHERE `id` = %d AND `char_id` = %u", ad.achievement_id, char_id);
+
+	if (SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf))) {
+		Sql_ShowDebug(sql_handle);
+		StringBuf_Clear(&buf);
+		return false;
+	}
+
+	StringBuf_Clear(&buf);
+
+	return true;
+}
+
+/**
+ * Notifies the map-server of the result of saving a character's achievementlog.
+ */
+void mapif_achievement_save( int fd, uint32 char_id, bool success ){
+	WFIFOHEAD(fd, 7);
+	WFIFOW(fd, 0) = 0x3863;
+	WFIFOL(fd, 2) = char_id;
+	WFIFOB(fd, 6) = success;
+	WFIFOSET(fd, 7);
+}
+
+/**
+ * Handles the save request from mapserver for a character's achievementlog.
+ * Received achievements are saved, and an ack is sent back to the map server.
+ * @see inter_parse_frommap
+ */
+int mapif_parse_achievement_save(int fd)
+{
+	int i, j, k, old_n, new_n = (RFIFOW(fd, 2) - 8) / sizeof(struct achievement);
+	uint32 char_id = RFIFOL(fd, 4);
+	struct achievement *old_ad = NULL, *new_ad = NULL;
+	bool success = true;
+
+	if (new_n > 0)
+		new_ad = (struct achievement *)RFIFOP(fd, 8);
+
+	old_ad = mapif_achievements_fromsql(char_id, &old_n);
+
+	for (i = 0; i < new_n; i++) {
+		ARR_FIND(0, old_n, j, new_ad[i].achievement_id == old_ad[j].achievement_id);
+		if (j < old_n) { // Update existing achievements
+			// Only counts, complete, and reward are changable.
+			ARR_FIND(0, MAX_ACHIEVEMENT_OBJECTIVES, k, new_ad[i].count[k] != old_ad[j].count[k]);
+			if (k != MAX_ACHIEVEMENT_OBJECTIVES || new_ad[i].completed != old_ad[j].completed || new_ad[i].rewarded != old_ad[j].rewarded) {
+				if ((success = mapif_achievement_update(char_id, new_ad[i])) == false)
+					break;
+			}
+
+			if (j < (--old_n)) {
+				// Compact array
+				memmove(&old_ad[j], &old_ad[j + 1], sizeof(struct achievement) * (old_n - j));
+				memset(&old_ad[old_n], 0, sizeof(struct achievement));
+			}
+		} else { // Add new achievements
+			if (new_ad[i].achievement_id) {
+				if ((success = mapif_achievement_add(char_id, new_ad[i])) == false)
+					break;
+			}
+		}
+	}
+
+	for (i = 0; i < old_n; i++) { // Achievements not in new_ad but in old_ad are to be erased.
+		if ((success = mapif_achievement_delete(char_id, old_ad[i].achievement_id)) == false)
+			break;
+	}
+
+	if (old_ad)
+		aFree(old_ad);
+
+	mapif_achievement_save(fd, char_id, success);
+
+	return 0;
+}
+
+/**
+ * Sends the achievementlog of a character to the map-server.
+ */
+void mapif_achievement_load( int fd, uint32 char_id ){
+	struct achievement *tmp_achievementlog = NULL;
+	int num_achievements = 0;
+
+	tmp_achievementlog = mapif_achievements_fromsql(char_id, &num_achievements);
+
+	WFIFOHEAD(fd, num_achievements * sizeof(struct achievement) + 8);
+	WFIFOW(fd, 0) = 0x3862;
+	WFIFOW(fd, 2) = num_achievements * sizeof(struct achievement) + 8;
+	WFIFOL(fd, 4) = char_id;
+
+	if (num_achievements > 0)
+		memcpy(WFIFOP(fd, 8), tmp_achievementlog, sizeof(struct achievement) * num_achievements);
+
+	WFIFOSET(fd, num_achievements * sizeof(struct achievement) + 8);
+
+	if (tmp_achievementlog)
+		aFree(tmp_achievementlog);
+}
+
+/**
+ * Sends achievementlog to the map server
+ * NOTE: Achievements sent to the player are only completed ones
+ * @see inter_parse_frommap
+ */
+int mapif_parse_achievement_load(int fd)
+{
+	mapif_achievement_load( fd, RFIFOL(fd, 2) );
+
+	return 0;
+}
+
+/**
+ * Notify the map-server if claiming the reward has succeeded.
+ */
+void mapif_achievement_reward( int fd, uint32 char_id, int32 achievement_id, time_t rewarded ){
+	WFIFOHEAD(fd, 14);
+	WFIFOW(fd, 0) = 0x3864;
+	WFIFOL(fd, 2) = char_id;
+	WFIFOL(fd, 6) = achievement_id;
+	WFIFOL(fd, 10) = (uint32)rewarded;
+	WFIFOSET(fd, 14);
+}
+
+/**
+ * Request of the map-server that a player claimed his achievement rewards.
+ * @see inter_parse_frommap
+ */
+int mapif_parse_achievement_reward(int fd){
+	time_t current = time(NULL);
+	uint32 char_id = RFIFOL(fd, 2);
+	int32 achievement_id = RFIFOL(fd, 6);
+
+	if( Sql_Query( sql_handle, "UPDATE `%s` SET `rewarded` = FROM_UNIXTIME('%u') WHERE `char_id`='%u' AND `id` = '%d' AND `completed` IS NOT NULL AND `rewarded` IS NULL", schema_config.achievement_table, (uint32)current, char_id, achievement_id ) == SQL_ERROR ||
+		Sql_NumRowsAffected(sql_handle) <= 0 ){
+		current = 0;
+	}else if( RFIFOW(fd,10) > 0 ){ // Do not send a mail if no item reward
+		char mail_sender[NAME_LENGTH];
+		char mail_receiver[NAME_LENGTH];
+		char mail_title[MAIL_TITLE_LENGTH];
+		char mail_text[MAIL_BODY_LENGTH];
+		struct item item;
+
+		memset(&item, 0, sizeof(struct item));
+		item.nameid = RFIFOW(fd, 10);
+		item.amount = RFIFOL(fd, 12);
+		item.identify = 1;
+
+		safesnprintf(mail_sender, NAME_LENGTH, char_msg_txt(227)); // 227: GM
+		safestrncpy(mail_receiver, RFIFOCP(fd,16), NAME_LENGTH);
+		safesnprintf(mail_title, MAIL_TITLE_LENGTH, char_msg_txt(228)); // 228: Achievement Reward Mail
+		safesnprintf(mail_text, MAIL_BODY_LENGTH, char_msg_txt(229), RFIFOCP(fd,16+NAME_LENGTH) ); // 229: [%s] Achievement Reward.
+
+		if( !mail_sendmail(0, mail_sender, char_id, mail_receiver, mail_title, mail_text, 0, &item, 1) ){
+			current = 0;
+		}
+	}
+
+	mapif_achievement_reward(fd, char_id, achievement_id, current);
+
+	return 0;
+}
+
+/**
+ * Parses achievementlog related packets from the map server.
+ * @see inter_parse_frommap
+ */
+int inter_achievement_parse_frommap(int fd)
+{
+	switch (RFIFOW(fd, 0)) {
+		case 0x3062: mapif_parse_achievement_load(fd); break;
+		case 0x3063: mapif_parse_achievement_save(fd); break;
+		case 0x3064: mapif_parse_achievement_reward(fd); break;
+		default:
+			return 0;
+	}
+	return 1;
+}

+ 9 - 0
src/char/int_achievement.h

@@ -0,0 +1,9 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef _INT_ACHIEVEMENT_SQL_H_
+#define _INT_ACHIEVEMENT_SQL_H_
+
+int inter_achievement_parse_frommap(int fd);
+
+#endif /* _INT_ACHIEVEMENT_SQL_H_ */

+ 1 - 1
src/char/int_guild.c

@@ -1096,7 +1096,7 @@ int mapif_guild_master_changed(struct guild *g, int aid, int cid, time_t time)
 	WBUFL(buf,2)=g->guild_id;
 	WBUFL(buf,6)=aid;
 	WBUFL(buf,10)=cid;
-	WBUFL(buf,14)=time;
+	WBUFL(buf,14)=(uint32)time;
 	chmapif_sendall(buf,18);
 	return 0;
 }

+ 6 - 2
src/char/int_mail.c

@@ -578,7 +578,7 @@ static void mapif_parse_Mail_send(int fd)
 	mapif_Mail_new(&msg); // notify recipient
 }
 
-void mail_sendmail(int send_id, const char* send_name, int dest_id, const char* dest_name, const char* title, const char* body, int zeny, struct item *item, int amount)
+bool mail_sendmail(int send_id, const char* send_name, int dest_id, const char* dest_name, const char* title, const char* body, int zeny, struct item *item, int amount)
 {
 	struct mail_message msg;
 	memset(&msg, 0, sizeof(struct mail_message));
@@ -601,8 +601,12 @@ void mail_sendmail(int send_id, const char* send_name, int dest_id, const char*
 	msg.timestamp = time(NULL);
 	msg.type = MAIL_INBOX_NORMAL;
 
-	mail_savemessage(&msg);
+	if( !mail_savemessage(&msg) ){
+		return false;
+	}
+
 	mapif_Mail_new(&msg);
+	return true;
 }
 
 static void mapif_Mail_receiver_send( int fd, int requesting_char_id, int char_id, int class_, int base_level, const char* name ){

+ 1 - 1
src/char/int_mail.h

@@ -12,7 +12,7 @@ int mail_return_timer( int tid, unsigned int tick, int id, intptr_t data );
 int mail_delete_timer( int tid, unsigned int tick, int id, intptr_t data );
 
 int inter_mail_parse_frommap(int fd);
-void mail_sendmail(int send_id, const char* send_name, int dest_id, const char* dest_name, const char* title, const char* body, int zeny, struct item *item, int amount);
+bool mail_sendmail(int send_id, const char* send_name, int dest_id, const char* dest_name, const char* title, const char* body, int zeny, struct item *item, int amount);
 
 int inter_mail_sql_init(void);
 void inter_mail_sql_final(void);

+ 47 - 11
src/char/int_party.c

@@ -31,6 +31,7 @@ int party_check_empty(struct party_data *p);
 int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type);
 int party_check_exp_share(struct party_data *p);
 int mapif_party_optionchanged(int fd,struct party *p, uint32 account_id, int flag);
+int party_check_family_share(struct party_data *p);
 
 //Updates party's level range and unsets even share if broken.
 static int int_party_check_lv(struct party_data *p) {
@@ -40,9 +41,9 @@ static int int_party_check_lv(struct party_data *p) {
 	p->max_lv = 0;
 	for(i=0;i<MAX_PARTY;i++){
 		/**
-		 * - If not online OR if it's a family party and this is the child (doesn't affect exp range)
+		 * - If not online (doesn't affect exp range)
 		 **/
-		if(!p->party.member[i].online || p->party.member[i].char_id == p->family )
+		if (!p->party.member[i].online)
 			continue;
 
 		lv=p->party.member[i].lv;
@@ -69,7 +70,8 @@ static void int_party_calc_state(struct party_data *p)
 
 	//Check party size
 	for(i=0;i<MAX_PARTY;i++){
-		if (!p->party.member[i].lv) continue;
+		if (!p->party.member[i].lv) 
+			continue;
 		p->size++;
 		if(p->party.member[i].online)
 			p->party.count++;
@@ -91,11 +93,9 @@ static void int_party_calc_state(struct party_data *p)
 	//max/min levels.
 	for(i=0;i<MAX_PARTY;i++){
 		unsigned int lv=p->party.member[i].lv;
-		if (!lv) continue;
-		if(p->party.member[i].online &&
-			//On families, the kid is not counted towards exp share rules.
-			p->party.member[i].char_id != p->family)
-		{
+		if (!lv) 
+			continue;
+		if (p->party.member[i].online) {
 			if( lv < p->min_lv ) p->min_lv=lv;
 			if( p->max_lv < lv ) p->max_lv=lv;
 		}
@@ -301,10 +301,45 @@ struct party_data* search_partyname(char* str)
 	return p;
 }
 
+int party_check_family_share(struct party_data *p) {
+	int i;
+	unsigned short map = 0;
+	if (!p->family)
+		return 0;
+	for (i = 0; i < MAX_PARTY; i++) {
+		if (p->party.member[i].char_id == p->family) {
+			map = p->party.member[i].map;
+			break;
+		}
+	}
+
+	for (i = 0; i < MAX_PARTY; i++) {
+		struct party_member * mem = &(p->party.member[i]);
+		if (mem->lv == 0)
+			continue;
+		if (p->family == mem->char_id) {
+			continue;
+		}
+		if (mem->online == 0) {
+			//everyone should be online to share
+			return 0;
+		}
+		if (mem->map != map) {
+			//everyone should be on the same map
+			return 0;
+		}
+		if (mem->lv < 70) {
+			//parents must both be above 70
+			return 0;
+		}
+	}
+	return 1;
+}
+
 // Returns whether this party can keep having exp share or not.
 int party_check_exp_share(struct party_data *p)
 {
-	return (p->party.count < 2 || p->max_lv - p->min_lv <= party_share_level);
+	return (p->party.count < 2 || p->max_lv - p->min_lv <= party_share_level || party_check_family_share(p));
 }
 
 // Is there any member in the party?
@@ -521,7 +556,6 @@ static void mapif_parse_PartyInfo(int fd, int party_id, uint32 char_id)
 {
 	struct party_data *p;
 	p = inter_party_fromsql(party_id);
-
 	if (p)
 		mapif_party_info(fd, &p->party, char_id);
 	else
@@ -575,7 +609,8 @@ int mapif_parse_PartyChangeOption(int fd,int party_id,uint32 account_id,int exp,
 
 	if(!p)
 		return 0;
-
+	if (p->size == 2 || p->size == 3) //check family state. Also accept either of their parents.
+		int_party_calc_state(p);
 	p->party.exp=exp;
 	if( exp && !party_check_exp_share(p) ){
 		flag|=0x01;
@@ -692,6 +727,7 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, uint32 account_id, uint32 c
 	if (p->party.member[i].map != map) {
 		p->party.member[i].map = map;
 		mapif_party_membermoved(&p->party, i);
+		int_party_check_lv(p);
 	}
 	return 0;
 }

+ 3 - 1
src/char/inter.c

@@ -22,6 +22,7 @@
 #include "int_quest.h"
 #include "int_elemental.h"
 #include "int_clan.h"
+#include "int_achievement.h"
 
 #include <stdlib.h>
 
@@ -51,7 +52,7 @@ int inter_recv_packet_length[] = {
 	-1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1,	// 3030-
 	-1, 9, 0, 0,  0, 0, 0, 0,  8, 6,11,10, 10,-1,6+NAME_LENGTH, 0,	// 3040-
 	-1,-1,10,10,  0,-1,12, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3050-  Auction System [Zephyrus]
-	 6,-1, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3060-  Quest system [Kevin] [Inkfish]
+	 6,-1, 6,-1, 16+NAME_LENGTH+ACHIEVEMENT_NAME_LENGTH, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3060-  Quest system [Kevin] [Inkfish] / Achievements [Aleos]
 	-1,10, 6,-1,  0, 0, 0, 0,  0, 0, 0, 0, -1,10,  6,-1,	// 3070-  Mercenary packets [Zephyrus], Elemental packets [pakpil]
 	48,14,-1, 6,  0, 0, 0, 0,  0, 0,13,-1,  0, 0,  0, 0,	// 3080-  Pet System, Storage
 	-1,10,-1, 6,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3090-  Homunculus packets [albator]
@@ -1409,6 +1410,7 @@ int inter_parse_frommap(int fd)
 		  || inter_auction_parse_frommap(fd)
 		  || inter_quest_parse_frommap(fd)
 		  || inter_clan_parse_frommap(fd)
+		  || inter_achievement_parse_frommap(fd)
 		   )
 			break;
 		else

+ 20 - 10
src/common/Makefile.in

@@ -2,7 +2,7 @@
 #COMMON_OBJ = $(ls *.c | grep -viw sql.c | sed -e "s/\.c/\.o/g")
 COMMON_OBJ = core.o socket.o timer.o db.o nullpo.o malloc.o showmsg.o strlib.o utils.o \
 	grfio.o mapindex.o ers.o md5calc.o minicore.o minisocket.o minimalloc.o random.o des.o \
-	conf.o thread.o mutex.o raconf.o mempool.o msg_conf.o cli.o sql.o
+	conf.o thread.o mutex.o raconf.o mempool.o msg_conf.o cli.o sql.o yamlwrapper.o
 COMMON_DIR_OBJ = $(COMMON_OBJ:%=obj/%)
 COMMON_H = $(shell ls ../common/*.h)
 COMMON_AR = obj/common.a
@@ -15,6 +15,12 @@ LIBCONFIG_H = $(shell ls ../../3rdparty/libconfig/*.h)
 LIBCONFIG_AR = ../../3rdparty/libconfig/obj/libconfig.a
 LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig
 
+YAML_CPP_OBJ = $(shell find ../../3rdparty/yaml-cpp/ -type f -name "*.cpp" | sed -e "s/\.cpp/\.o/g" )
+YAML_CPP_DIR_OBJ = $(YAML_CPP_OBJ:%=obj/%)
+YAML_CPP_AR = ../../3rdparty/yaml-cpp/obj/yaml-cpp.a
+YAML_CPP_H = $(shell find ../../3rdparty/yaml-cpp/ -type f -name "*.h")
+YAML_CPP_INCLUDE = -I../../3rdparty/yaml-cpp/include
+
 HAVE_MYSQL=@HAVE_MYSQL@
 ifeq ($(HAVE_MYSQL),yes)
 	SERVER_DEPENDS=common
@@ -59,23 +65,23 @@ $(COMMON_AR): $(COMMON_DIR_OBJ)
 	@echo "	AR	$@"
 	@@AR@ rcs $(COMMON_AR) $(COMMON_DIR_OBJ)
 
-common: obj $(COMMON_DIR_OBJ) $(MT19937AR_OBJ) $(LIBCONFIG_AR) $(COMMON_AR)
+common: obj $(COMMON_DIR_OBJ) $(MT19937AR_OBJ) $(LIBCONFIG_AR) $(YAML_CPP_AR) $(COMMON_AR)
 
-obj/%.o: %.c $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H)
+obj/%.o: %.c $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H) $(YAML_CPP_H)
 	@echo "	CC	$<"
-	@@CC@ @CFLAGS_AR@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+	@@CC@ @CFLAGS_AR@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(YAML_CPP_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
 
-obj/%.o: %.cpp $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H)
+obj/%.o: %.cpp $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H) $(YAML_CPP_H)
 	@echo "	CXX	$<"
-	@@CXX@ $(CXXFLAG) @CFLAGS_AR@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+	@@CXX@ $(CXXFLAG) @CFLAGS_AR@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(YAML_CPP_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
 
-obj/mini%.o: %.c $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H)
+obj/mini%.o: %.c $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H) $(YAML_CPP_H)
 	@echo "	CC	$<"
-	@@CC@ @CFLAGS_AR@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) @MYSQL_CFLAGS@ -DMINICORE @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+	@@CC@ @CFLAGS_AR@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(YAML_CPP_INCLUDE) @MYSQL_CFLAGS@ -DMINICORE @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
 
-obj/mini%.o: %.cpp $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H)
+obj/mini%.o: %.cpp $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H) $(YAML_CPP_H)
 	@echo "	CXX	$<"
-	@@CXX@ $(CXXFLAG) @CFLAGS_AR@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) @MYSQL_CFLAGS@ -DMINICORE @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+	@@CXX@ $(CXXFLAG) @CFLAGS_AR@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(YAML_CPP_INCLUDE) @MYSQL_CFLAGS@ -DMINICORE @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
 
 # missing object files
 $(MT19937AR_OBJ):
@@ -83,3 +89,7 @@ $(MT19937AR_OBJ):
 
 $(LIBCONFIG_AR):
 	@$(MAKE) -C ../../3rdparty/libconfig
+
+$(YAML_CPP_AR):
+	@$(MAKE) -C ../../3rdparty/yaml-cpp
+

+ 8 - 4
src/common/core.cpp

@@ -247,9 +247,6 @@ const char* get_svn_revision(void) {
 }
 #endif
 
-// GIT path
-#define GIT_ORIGIN "refs/remotes/origin/master"
-
 // Grabs the hash from the last time the user updated their working copy (last pull)
 const char *get_git_hash (void) {
 	static char GitHash[41] = ""; //Sha(40) + 1
@@ -258,7 +255,8 @@ const char *get_git_hash (void) {
 	if( GitHash[0] != '\0' )
 		return GitHash;
 
-	if( (fp = fopen(".git/" GIT_ORIGIN, "r")) != NULL ) {
+	if( (fp = fopen(".git/refs/remotes/origin/master", "r")) != NULL || // Already pulled once
+		(fp = fopen(".git/refs/heads/master", "r")) != NULL ) { // Cloned only
 		char line[64];
 		char *rev = (char*)malloc(sizeof(char) * 50);
 
@@ -381,5 +379,11 @@ int main (int argc, char **argv)
 
 	malloc_final();
 
+#if defined(BUILDBOT)
+	if( buildbotflag ){
+		exit(EXIT_FAILURE);
+	}
+#endif
+
 	return 0;
 }

+ 2 - 2
src/common/ers.c

@@ -290,7 +290,7 @@ void ers_cache_size(ERS *self, unsigned int new_size) {
 }
 
 
-ERS *ers_new(uint32 size, char *name, enum ERSOptions options)
+ERS *ers_new(uint32 size, const char *name, enum ERSOptions options)
 {
 	struct ers_instance_t *instance;
 	CREATE(instance,struct ers_instance_t, 1);
@@ -308,7 +308,7 @@ ERS *ers_new(uint32 size, char *name, enum ERSOptions options)
 	instance->VTable.destroy = ers_obj_destroy;
 	instance->VTable.chunk_size = ers_cache_size;
 
-	instance->Name = ( options & ERS_OPT_FREE_NAME ) ? aStrdup(name) : name;
+	instance->Name = ( options & ERS_OPT_FREE_NAME ) ? (char *)aStrdup(name) : (char *)name;
 	instance->Options = options;
 
 	instance->Cache = ers_find_cache(size,instance->Options);

+ 1 - 1
src/common/ers.h

@@ -162,7 +162,7 @@ typedef struct eri {
  * @param The requested size of the entry in bytes
  * @return Interface of the object
  */
-ERS *ers_new(uint32 size, char *name, enum ERSOptions options);
+ERS *ers_new(uint32 size, const char *name, enum ERSOptions options);
 
 /**
  * Print a report about the current state of the Entry Reusage System.

+ 1 - 0
src/common/mapindex.h

@@ -54,6 +54,7 @@ extern "C" {
 #define MAP_MALAYA "malaya"
 #define MAP_ECLAGE "eclage"
 #define MAP_ECLAGE_IN "ecl_in01"
+#define MAP_LASAGNA "lasagna"
 
 const char* mapindex_getmapname(const char* string, char* output);
 const char* mapindex_getmapname_ext(const char* string, char* output);

+ 17 - 22
src/common/mmo.h

@@ -9,31 +9,10 @@
 #include "db.h"
 #include <time.h>
 
-// server->client protocol version
-//        0 - pre-?
-//        1 - ?                    - 0x196
-//        2 - ?                    - 0x78, 0x79
-//        3 - ?                    - 0x1c8, 0x1c9, 0x1de
-//        4 - ?                    - 0x1d7, 0x1d8, 0x1d9, 0x1da
-//        5 - 2003-12-18aSakexe+   - 0x1ee, 0x1ef, 0x1f0, ?0x1c4, 0x1c5?
-//        6 - 2004-03-02aSakexe+   - 0x1f4, 0x1f5
-//        7 - 2005-04-11aSakexe+   - 0x229, 0x22a, 0x22b, 0x22c
-// see conf/battle/client.conf for other version
-
 #ifndef PACKETVER
-	#define PACKETVER 20151104
-	//#define PACKETVER 20120410
+	#error Please define PACKETVER in src/config/packets.h
 #endif
 
-// Check if the specified packetversion supports the pincode system
-#define PACKETVER_SUPPORTS_PINCODE PACKETVER>=20110309
-
-/// Check if the client needs delete_date as remaining time and not the actual delete_date (actually it was tested for clients since 2013)
-#define PACKETVER_CHAR_DELETEDATE (PACKETVER > 20130000 && PACKETVER < 20141016) || PACKETVER >= 20150513
-
-// Check if the specified packetvresion supports the cashshop sale system
-#define PACKETVER_SUPPORTS_SALES PACKETVER>=20131223
-
 ///Remove/Comment this line to disable sc_data saving. [Skotlex]
 #define ENABLE_SC_SAVING
 /** Remove/Comment this line to disable server-side hot-key saving support [Skotlex]
@@ -162,6 +141,12 @@
 #define EL_CLASS_BASE 2114
 #define EL_CLASS_MAX (EL_CLASS_BASE+MAX_ELEMENTAL_CLASS-1)
 
+//Achievement System
+#define MAX_ACHIEVEMENT_RANK 20 /// Maximum achievement level
+#define MAX_ACHIEVEMENT_OBJECTIVES 10 /// Maximum different objectives in achievement_db.conf
+#define MAX_ACHIEVEMENT_DEPENDENTS 20 /// Maximum different dependents in achievement_db.conf
+#define ACHIEVEMENT_NAME_LENGTH 50 /// Max Achievement Name length
+
 #define MAX_WARP_ATTEMPTS 1000 /// Max amount of attempts to randomly warp a character onto valid coordinates
 
 enum item_types {
@@ -203,6 +188,15 @@ struct s_item_randomoption {
 	char param;
 };
 
+/// Achievement log entry
+struct achievement {
+	int achievement_id;                    ///< Achievement ID
+	int count[MAX_ACHIEVEMENT_OBJECTIVES]; ///< Counters of each achievement objective
+	time_t completed;                      ///< Date completed
+	time_t rewarded;                       ///< Received reward?
+	int score;                             ///< Amount of points achievement is worth
+};
+
 struct item {
 	int id;
 	unsigned short nameid;
@@ -501,6 +495,7 @@ struct mmo_charstatus {
 	uint32 uniqueitem_counter;
 
 	unsigned char hotkey_rowshift;
+	unsigned long title_id;
 };
 
 typedef enum mail_status {

+ 10 - 0
src/common/sql.c

@@ -352,6 +352,16 @@ uint64 Sql_NumRows(Sql* self)
 
 
 
+/// Returns the number of rows affected by the last query
+uint64 Sql_NumRowsAffected(Sql* self)
+{
+	if( self )
+		return (uint64)mysql_affected_rows(&self->handle);
+	return 0;
+}
+
+
+
 /// Fetches the next row.
 int Sql_NextRow(Sql* self)
 {

+ 7 - 0
src/common/sql.h

@@ -175,6 +175,13 @@ uint64 Sql_NumRows(Sql* self);
 
 
 
+/// Returns the number of rows affected by the last query
+///
+/// @return Number of rows
+uint64 Sql_NumRowsAffected(Sql* self);
+
+
+
 /// Fetches the next row.
 /// The data of the previous row is no longer valid.
 ///

+ 0 - 53
src/common/utils.c

@@ -358,59 +358,6 @@ float GetFloat(const unsigned char* buf)
 	return *((float*)(void*)&val);
 }
 
-uint32 date2version(int date) {
-	if(date < 20040906) return 5;
-	else if(date < 20040920) return 10;
-	else if(date < 20041005) return 11;
-	else if(date < 20041025) return 12;
-	else if(date < 20041129) return 13;
-	else if(date < 20050110) return 14;
-	else if(date < 20050509) return 15;
-	else if(date < 20050628) return 16;
-	else if(date < 20050718) return 17;
-	else if(date < 20050719) return 18;
-	else if(date < 20060327) return 19;
-	else if(date < 20070108) return 20;
-	else if(date < 20070212) return 21;
-	//wtf @FIXME
-	//else if(date < 20080910) return 22;
-	else if(date < 20080827) return 23;
-	else if(date < 20080910) return 24;
-	//unable to solve from date
-	else if(date < 20101124) return 25;
-	else if(date < 20111005) return 26;
-	else if(date < 20111102) return 27;
-	else if(date < 20120307) return 28;
-	else if(date < 20120410) return 29;
-	else if(date < 20120418) return 30;
-	else if(date < 20120618) return 31;
-	else if(date < 20120702) return 32;
-	else if(date < 20130320) return 33;
-	else if(date < 20130515) return 34;
-	else if(date < 20130522) return 35;
-	else if(date < 20130529) return 36;
-	else if(date < 20130605) return 37;
-	else if(date < 20130612) return 38;
-	else if(date < 20130618) return 39;
-	else if(date < 20130626) return 40;
-	else if(date < 20130703) return 41;
-	else if(date < 20130710) return 42;
-	else if(date < 20130717) return 43;
-	else if(date < 20130807) return 44;
-	else if(date < 20131223) return 45;
-	else if(date < 20140212) return 46;
-	//else if(date < 20140613) return 47;
-	//else if(date < 20141016) return 48;
-	else if(date < 20141022) return 50;
-	else if(date < 20150513) return 51;
-	else if(date < 20150916) return 52;
-	else if(date < 20151001) return 53;
-	else if(date < 20151104) return 54;
-	else if(date >= 20151104) return 55;
-
-	else return 30; //default
-}
-
 /// calculates the value of A / B, in percent (rounded down)
 unsigned int get_percentage(const unsigned int A, const unsigned int B)
 {

+ 0 - 2
src/common/utils.h

@@ -50,8 +50,6 @@ extern uint32 GetULong(const unsigned char* buf);
 extern int32 GetLong(const unsigned char* buf);
 extern float GetFloat(const unsigned char* buf);
 
-uint32 date2version(int date);
-
 int levenshtein(const char *s1, const char *s2);
 
 #ifdef __cplusplus

+ 57 - 5
src/common/yamlwrapper.cpp

@@ -31,8 +31,8 @@ yamlwrapper::yamlwrapper(YAML::Node node) {
 	this->root = node;
 }
 
-yamliterator::yamliterator(YAML::Node sequence) {
-	this->sequence = sequence;
+yamliterator::yamliterator(YAML::Node sequence_) {
+	this->sequence = sequence_;
 	this->index = 0;
 }
 
@@ -41,13 +41,21 @@ yamliterator* yamlwrapper::iterator() {
 }
 
 yamlwrapper* yaml_load_file(const char* file_name) {
-	YAML::Node node = YAML::LoadFile(file_name);
-	if (!node.IsDefined())
+	YAML::Node node;
+
+	try {
+		node = YAML::LoadFile(file_name);
+		if (!node.IsDefined())
+			return NULL;
+	} catch (YAML::ParserException &e) {
+		ShowError("YAML Exception Caught: %s\n", e.what());
 		return NULL;
+	}
+
 	return new yamlwrapper(node);
 }
 
-extern "C++" YAML::Node yaml_get_node(YAML::Node& node, std::string& key) {
+extern "C++" YAML::Node yaml_get_node(const YAML::Node& node,const std::string& key) {
 	if (key.empty())
 		return node;
 
@@ -107,6 +115,50 @@ bool yaml_get_boolean(yamlwrapper* wrapper, const char* key) {
 	return yaml_get_value<bool>(wrapper, key);
 }
 
+char* yaml_as_c_string(yamlwrapper* wrapper) {
+	std::string cpp_str = wrapper->root.as<std::string>();
+	const char* c_str = cpp_str.c_str();
+	size_t str_size = std::strlen(c_str) + 1;
+	char* buf = (char*)aCalloc(1, str_size);
+	strcpy(buf, c_str);
+	return buf;
+}
+
+extern "C++" {
+	template<typename T>
+	T yaml_as_value(yamlwrapper* wrapper) {
+		if (wrapper == nullptr)
+			return {};
+		try {
+			return wrapper->root.as<T>();
+		}
+		catch (const std::exception& e) {
+			ShowError("Error during YAML node value resolving in node %s.\n", e.what());
+			return {};
+		}
+	}
+}
+
+int yaml_as_int(yamlwrapper* wrapper) {
+	return yaml_as_value<int>(wrapper);
+}
+
+int16 yaml_as_int16(yamlwrapper* wrapper) {
+	return yaml_as_value<int16>(wrapper);
+}
+
+int32 yaml_as_int32(yamlwrapper* wrapper) {
+	return yaml_as_value<int32>(wrapper);
+}
+
+int64 yaml_as_int64(yamlwrapper* wrapper) {
+	return yaml_as_value<int64>(wrapper);
+}
+
+bool yaml_as_boolean(yamlwrapper* wrapper) {
+	return yaml_as_value<bool>(wrapper);
+}
+
 bool yaml_node_is_defined(yamlwrapper* wrapper, const char* key) {
 	if (wrapper == nullptr || key == nullptr)
 		return false;

+ 7 - 1
src/common/yamlwrapper.h

@@ -42,7 +42,7 @@ class yamliterator {
 public:
 	YAML::Node sequence;
 	unsigned int index;
-	yamliterator(YAML::Node sequence);
+	yamliterator(YAML::Node sequence_);
 };
 
 class yamlwrapper {
@@ -65,6 +65,12 @@ int16 yaml_get_int16(yamlwrapper* wrapper, const char* key);
 int32 yaml_get_int32(yamlwrapper* wrapper, const char* key);
 int64 yaml_get_int64(yamlwrapper* wrapper, const char* key);
 bool yaml_get_boolean(yamlwrapper* wrapper, const char* key);
+char* yaml_as_c_string(yamlwrapper* wrapper);
+int yaml_as_int(yamlwrapper* wrapper);
+int16 yaml_as_int16(yamlwrapper* wrapper);
+int32 yaml_as_int32(yamlwrapper* wrapper);
+int64 yaml_as_int64(yamlwrapper* wrapper);
+bool yaml_as_boolean(yamlwrapper* wrapper);
 bool yaml_node_is_defined(yamlwrapper* wrapper, const char* key);
 yamlwrapper* yaml_get_subnode(yamlwrapper* wrapper, const char* key);
 yamliterator* yaml_get_iterator(yamlwrapper* wrapper);

+ 5 - 6
src/config/core.h

@@ -8,6 +8,8 @@
  * For detailed guidance on these check http://rathena.org/wiki/SRC/config/
  **/
 
+#include "../custom/defines_pre.h"
+
 /// Max number of items on @autolootid list
 #define AUTOLOOTITEM_SIZE 10
 
@@ -76,12 +78,6 @@
 	#define MAX_CHAR_BILLING 0 // This must be less than MAX_CHARS
 #endif
 
-/// Comment to disable the official packet obfuscation support.
-/// When enabled, make sure there is value for 'packet_keys' of used packet version or
-/// defined 'packet_keys_use' in db/[import/]packet_db.txt.
-/// This requires PACKETVER 2011-08-17 or newer.
-#define PACKET_OBFUSCATION
-
 /// Comment to disable warnings for deprecated script commands
 #define SCRIPT_COMMAND_DEPRECATION
 
@@ -91,6 +87,7 @@
 /**
  * No settings past this point
  **/
+#include "./packets.h"
 #include "./renewal.h"
 #include "./secure.h"
 #include "./classes/general.h"
@@ -100,4 +97,6 @@
  **/
 #include "./const.h"
 
+#include "../custom/defines_post.h"
+
 #endif // _CONFIG_CORE_H_

+ 63 - 0
src/config/packets.h

@@ -0,0 +1,63 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+#ifndef _CONFIG_PACKETS_H_
+#define _CONFIG_PACKETS_H_
+
+/**
+ * rAthena configuration file (http://rathena.org)
+ * For detailed guidance on these check http://rathena.org/wiki/SRC/config/
+ **/
+
+#ifndef PACKETVER
+	#define PACKETVER 20151104
+#endif
+
+#ifndef PACKETVER_RE
+	/// From this point on only kRO RE clients are supported
+	#if PACKETVER > 20151104
+		#define PACKETVER_RE
+	#endif
+#endif
+
+#if PACKETVER >= 20110817
+	/// Comment to disable the official packet obfuscation support.
+	/// This requires PACKETVER 2011-08-17 or newer.
+	#ifndef PACKET_OBFUSCATION
+		#define PACKET_OBFUSCATION
+
+		// Define these inside src/custom/defines_pre.h or src/custom/defines_post.h
+		//#define PACKET_OBFUSCATION_KEY1 <key1>
+		//#define PACKET_OBFUSCATION_KEY2 <key2>
+		//#define PACKET_OBFUSCATION_KEY3 <key3>
+
+		/// Comment this to disable warnings for missing client side encryption
+		#define PACKET_OBFUSCATION_WARN
+	#endif
+#else
+	#if defined(PACKET_OBFUSCATION)
+		#error You enabled packet obfuscation for a version which is too old. Minimum supported client is 2011-08-17.
+	#endif
+#endif
+
+#ifndef DUMP_UNKNOWN_PACKET
+	//#define DUMP_UNKNOWN_PACKET
+#endif
+
+#ifndef DUMP_INVALID_PACKET
+	//#define DUMP_INVALID_PACKET
+#endif
+
+/**
+ * No settings past this point
+ **/
+
+/// Check if the specified packetversion supports the pincode system
+#define PACKETVER_SUPPORTS_PINCODE PACKETVER >= 20110309
+
+/// Check if the client needs delete_date as remaining time and not the actual delete_date (actually it was tested for clients since 2013)
+#define PACKETVER_CHAR_DELETEDATE (PACKETVER > 20130000 && PACKETVER <= 20141022) || PACKETVER >= 20150513
+
+/// Check if the specified packetvresion supports the cashshop sale system
+#define PACKETVER_SUPPORTS_SALES PACKETVER >= 20131223
+
+#endif // _CONFIG_PACKETS_H_

+ 13 - 0
src/custom/defines_post.h

@@ -0,0 +1,13 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+#ifndef _CONFIG_CUSTOM_DEFINES_POST_H_
+#define _CONFIG_CUSTOM_DEFINES_POST_H_
+
+/**
+ * rAthena configuration file (http://rathena.org)
+ * For detailed guidance on these check http://rathena.org/wiki/SRC/config/
+ **/
+
+
+
+#endif // _CONFIG_CUSTOM_DEFINES_POST_H_

+ 13 - 0
src/custom/defines_pre.h

@@ -0,0 +1,13 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+#ifndef _CONFIG_CUSTOM_DEFINES_PRE_H_
+#define _CONFIG_CUSTOM_DEFINES_PRE_H_
+
+/**
+ * rAthena configuration file (http://rathena.org)
+ * For detailed guidance on these check http://rathena.org/wiki/SRC/config/
+ **/
+
+
+
+#endif // _CONFIG_CUSTOM_DEFINES_PRE_H_

+ 0 - 14
src/login/login.cpp

@@ -303,13 +303,6 @@ int login_mmo_auth(struct login_session_data* sd, bool isServer) {
 
 	}
 
-	//Client Version check
-	if( login_config.check_client_version && sd->version != login_config.client_version_to_connect ){
-		ShowNotice("Invalid version (account: '%s', auth_vers: '%d', received version: '%d', ip: %s)\n",
-			sd->userid, login_config.client_version_to_connect, sd->version, ip);
-		return 5;
-	}
-
 	len = strnlen(sd->userid, NAME_LENGTH);
 
 	// Account creation with _M/_F
@@ -591,10 +584,6 @@ bool login_config_read(const char* cfgName, bool normal) {
 			login_config.new_acc_length_limit = (bool)config_switch(w2);
 		else if(!strcmpi(w1, "start_limited_time"))
 			login_config.start_limited_time = atoi(w2);
-		else if(!strcmpi(w1, "check_client_version"))
-			login_config.check_client_version = (bool)config_switch(w2);
-		else if(!strcmpi(w1, "client_version_to_connect"))
-			login_config.client_version_to_connect = strtoul(w2, NULL, 10);
 		else if(!strcmpi(w1, "use_MD5_passwords"))
 			login_config.use_md5_passwds = (bool)config_switch(w2);
 		else if(!strcmpi(w1, "group_id_to_connect"))
@@ -701,9 +690,6 @@ void login_set_defaults() {
 	login_config.use_md5_passwds = false;
 	login_config.group_id_to_connect = -1;
 	login_config.min_group_id_to_connect = -1;
-	login_config.check_client_version = false;
-	login_config.client_version_to_connect = date2version(PACKETVER); //20120410 => 30
-	ShowInfo("loginconfig: client_version_to_connect = %d\n",login_config.client_version_to_connect);
 
 	login_config.ipban = true;
 	login_config.dynamic_pass_failure_ban = true;

+ 0 - 4
src/login/login.h

@@ -46,7 +46,6 @@ struct login_session_data {
 	char lastlogin[24];		///date when last logged, Y-M-D HH:MM:SS
 	uint8 group_id;			///groupid of account
 	uint8 clienttype;		/// ???
-	uint32 version;			///version contained in clientinfo
 
 	uint8 client_hash[16];		///hash of client
 	int has_client_hash;		///client ha sent an hash
@@ -86,8 +85,6 @@ struct Login_Config {
 	bool use_md5_passwds;                           /// work with password hashes instead of plaintext passwords?
 	int group_id_to_connect;                        /// required group id to connect
 	int min_group_id_to_connect;                    /// minimum group id to connect
-	bool check_client_version;                      /// check the clientversion set in the clientinfo ?
-	uint32 client_version_to_connect;               /// the client version needed to connect (if checking is enabled)
 
 	bool ipban;                                     /// perform IP blocking (via contents of `ipbanlist`) ?
 	bool dynamic_pass_failure_ban;                  /// automatic IP blocking due to failed login attempts ?
@@ -143,7 +140,6 @@ struct auth_node {
 	uint32 login_id2;
 	uint32 ip;
 	char sex;
-	uint32 version;
 	uint8 clienttype;
 };
 extern DBMap* auth_db; // uint32 account_id -> struct auth_node*

+ 6 - 8
src/login/loginchrif.c

@@ -96,7 +96,7 @@ int logchrif_parse_reqauth(int fd, int id,char* ip){
 			//ShowStatus("Char-server '%s': authentication of the account %d accepted (ip: %s).\n", server[id].name, account_id, ip);
 
 			// send ack
-			WFIFOHEAD(fd,25);
+			WFIFOHEAD(fd,21);
 			WFIFOW(fd,0) = 0x2713;
 			WFIFOL(fd,2) = account_id;
 			WFIFOL(fd,6) = login_id1;
@@ -104,15 +104,14 @@ int logchrif_parse_reqauth(int fd, int id,char* ip){
 			WFIFOB(fd,14) = sex;
 			WFIFOB(fd,15) = 0;// ok
 			WFIFOL(fd,16) = request_id;
-			WFIFOL(fd,20) = node->version;
-			WFIFOB(fd,24) = node->clienttype;
-			WFIFOSET(fd,25);
+			WFIFOB(fd,20) = node->clienttype;
+			WFIFOSET(fd,21);
 
 			// each auth entry can only be used once
 			idb_remove(auth_db, account_id);
 		}else{// authentication not found
 			ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", ch_server[id].name, account_id, ip);
-			WFIFOHEAD(fd,25);
+			WFIFOHEAD(fd,21);
 			WFIFOW(fd,0) = 0x2713;
 			WFIFOL(fd,2) = account_id;
 			WFIFOL(fd,6) = login_id1;
@@ -120,9 +119,8 @@ int logchrif_parse_reqauth(int fd, int id,char* ip){
 			WFIFOB(fd,14) = sex;
 			WFIFOB(fd,15) = 1;// auth failed
 			WFIFOL(fd,16) = request_id;
-			WFIFOL(fd,20) = 0;
-			WFIFOB(fd,24) = 0;
-			WFIFOSET(fd,25);
+			WFIFOB(fd,20) = 0;
+			WFIFOSET(fd,21);
 		}
 	}
 	return 1;

+ 28 - 39
src/login/loginclif.c

@@ -159,7 +159,6 @@ static void logclif_auth_ok(struct login_session_data* sd) {
 	node->login_id2 = sd->login_id2;
 	node->sex = sd->sex;
 	node->ip = ip;
-	node->version = sd->version;
 	node->clienttype = sd->clienttype;
 	idb_put(auth_db, sd->account_id, node);
 	{
@@ -181,7 +180,7 @@ static void logclif_auth_ok(struct login_session_data* sd) {
     3 = Rejected from Server
     4 = You have been blocked by the GM Team
     5 = Your Game's EXE file is not the latest version
-    6 = Your are Prohibited to log in until %s
+    6 = You are prohibited to log in until %s
     7 = Server is jammed due to over populated
     8 = No more accounts may be connected from this company
     9 = MSI_REFUSE_BAN_BY_DBA
@@ -216,37 +215,33 @@ static void logclif_auth_failed(struct login_session_data* sd, int result) {
 	if( (result == 0 || result == 1) && login_config.dynamic_pass_failure_ban )
 		ipban_log(ip); // log failed password attempt
 
-//#if PACKETVER >= 20120000 /* not sure when this started */
-	if( sd->version >= date2version(20120000) ){ /* not sure when this started */
-		WFIFOHEAD(fd,26);
-		WFIFOW(fd,0) = 0x83e;
-		WFIFOL(fd,2) = result;
-		if( result != 6 )
-			memset(WFIFOP(fd,6), '\0', 20);
-		else { // 6 = Your are Prohibited to log in until %s
-			struct mmo_account acc;
-			AccountDB* accounts = login_get_accounts_db();
-			time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0;
-			timestamp2string(WFIFOCP(fd,6), 20, unban_time, login_config.date_format);
-		}
-		WFIFOSET(fd,26);
+#if PACKETVER >= 20120000 /* not sure when this started */
+	WFIFOHEAD(fd,26);
+	WFIFOW(fd,0) = 0x83e;
+	WFIFOL(fd,2) = result;
+	if( result != 6 )
+		memset(WFIFOP(fd,6), '\0', 20);
+	else { // 6 = You are prohibited to log in until %s
+		struct mmo_account acc;
+		AccountDB* accounts = login_get_accounts_db();
+		time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0;
+		timestamp2string(WFIFOCP(fd,6), 20, unban_time, login_config.date_format);
 	}
-//#else	
-	else {
-		WFIFOHEAD(fd,23);
-		WFIFOW(fd,0) = 0x6a;
-		WFIFOB(fd,2) = (uint8)result;
-		if( result != 6 )
-			memset(WFIFOP(fd,3), '\0', 20);
-		else { // 6 = Your are Prohibited to log in until %s
-			struct mmo_account acc;
-			AccountDB* accounts = login_get_accounts_db();
-			time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0;
-			timestamp2string(WFIFOCP(fd,3), 20, unban_time, login_config.date_format);
-		}
-		WFIFOSET(fd,23);
+	WFIFOSET(fd,26);
+#else
+	WFIFOHEAD(fd,23);
+	WFIFOW(fd,0) = 0x6a;
+	WFIFOB(fd,2) = (uint8)result;
+	if( result != 6 )
+		memset(WFIFOP(fd,3), '\0', 20);
+	else { // 6 = You are prohibited to log in until %s
+		struct mmo_account acc;
+		AccountDB* accounts = login_get_accounts_db();
+		time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0;
+		timestamp2string(WFIFOCP(fd,3), 20, unban_time, login_config.date_format);
 	}
-//#endif	
+	WFIFOSET(fd,23);
+#endif	
 }
 
 /**
@@ -306,7 +301,6 @@ static int logclif_parse_reqauth(int fd, struct login_session_data *sd, int comm
 		return 0;
 	else {
 		int result;
-		uint32 version;
 		char username[NAME_LENGTH];
 		char password[PASSWD_LENGTH];
 		unsigned char passhash[16];
@@ -320,8 +314,6 @@ static int logclif_parse_reqauth(int fd, struct login_session_data *sd, int comm
 			size_t uAccLen = strlen(accname);
 			size_t uTokenLen = RFIFOREST(fd) - 0x5C;
 
-			version = RFIFOL(fd,4);
-
 			if(uAccLen > NAME_LENGTH - 1 || uAccLen == 0 || uTokenLen > NAME_LENGTH - 1  || uTokenLen == 0)
 			{
 				logclif_auth_failed(sd, 3);
@@ -334,7 +326,6 @@ static int logclif_parse_reqauth(int fd, struct login_session_data *sd, int comm
 		}
 		else
 		{
-			version = RFIFOL(fd,2);
 			safestrncpy(username, RFIFOCP(fd,6), NAME_LENGTH);
 			if( israwpass )
 			{
@@ -350,11 +341,10 @@ static int logclif_parse_reqauth(int fd, struct login_session_data *sd, int comm
 		RFIFOSKIP(fd,RFIFOREST(fd)); // assume no other packet was sent
 
 		sd->clienttype = clienttype;
-		sd->version = version;
 		safestrncpy(sd->userid, username, NAME_LENGTH);
 		if( israwpass )
 		{
-			ShowStatus("Request for connection of %s (ip: %s) version=%d\n", sd->userid, ip,sd->version);
+			ShowStatus("Request for connection of %s (ip: %s)\n", sd->userid, ip);
 			safestrncpy(sd->passwd, password, NAME_LENGTH);
 			if( login_config.use_md5_passwds )
 				MD5_String(sd->passwd, sd->passwd);
@@ -362,7 +352,7 @@ static int logclif_parse_reqauth(int fd, struct login_session_data *sd, int comm
 		}
 		else
 		{
-			ShowStatus("Request for connection (passwdenc mode) of %s (ip: %s) version=%d\n", sd->userid, ip,sd->version);
+			ShowStatus("Request for connection (passwdenc mode) of %s (ip: %s)\n", sd->userid, ip);
 			bin2hex(sd->passwd, passhash, 16); // raw binary data here!
 			sd->passwdenc = PASSWORDENC;
 		}
@@ -430,7 +420,6 @@ static int logclif_parse_reqcharconnec(int fd, struct login_session_data *sd, ch
 		if( login_config.use_md5_passwds )
 			MD5_String(sd->passwd, sd->passwd);
 		sd->passwdenc = 0;
-		sd->version = login_config.client_version_to_connect; // hack to skip version check
 		server_ip = ntohl(RFIFOL(fd,54));
 		server_port = ntohs(RFIFOW(fd,58));
 		safestrncpy(server_name, RFIFOCP(fd,60), 20);

+ 15 - 6
src/map/Makefile.in

@@ -11,6 +11,12 @@ LIBCONFIG_H = $(shell ls ../../3rdparty/libconfig/*.h)
 LIBCONFIG_AR = ../../3rdparty/libconfig/obj/libconfig.a
 LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig
 
+YAML_CPP_OBJ = $(shell find ../../3rdparty/yaml-cpp/ -type f -name "*.cpp" | sed -e "s/\.cpp/\.o/g" )
+YAML_CPP_DIR_OBJ = $(YAML_CPP_OBJ:%=obj/%)
+YAML_CPP_AR = ../../3rdparty/yaml-cpp/obj/yaml-cpp.a
+YAML_CPP_H = $(shell find ../../3rdparty/yaml-cpp/ -type f -name "*.h")
+YAML_CPP_INCLUDE = -I../../3rdparty/yaml-cpp/include
+
 MAP_OBJ = $(shell ls *.c | sed -e "s/\.c/\.o/g") $(shell ls *.cpp | sed -e "s/\.cpp/\.o/g")
 MAP_DIR_OBJ = $(MAP_OBJ:%=obj/%)
 MAP_H = $(shell ls ../map/*.h) \
@@ -67,20 +73,20 @@ obj:
 
 # executables
 
-map-server: obj $(MAP_DIR_OBJ) $(COMMON_AR) $(LIBCONFIG_AR)
+map-server: obj $(MAP_DIR_OBJ) $(COMMON_AR) $(LIBCONFIG_AR) $(YAML_CPP_AR)
 	@echo "	LD	@OMAP@@EXEEXT@"
-	@@CXX@ @LDFLAGS@ -o ../../@OMAP@@EXEEXT@ $(MAP_DIR_OBJ) $(COMMON_AR) $(MT19937AR_OBJ) $(LIBCONFIG_AR) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@
+	@@CXX@ @LDFLAGS@ -o ../../@OMAP@@EXEEXT@ $(MAP_DIR_OBJ) $(COMMON_AR) $(MT19937AR_OBJ) $(LIBCONFIG_AR) $(YAML_CPP_AR) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@
 
 
 # map object files
 
-obj/%.o: %.c $(MAP_H) $(COMMON_H)  $(MT19937AR_H) $(LIBCONFIG_H)
+obj/%.o: %.c $(MAP_H) $(COMMON_H)  $(MT19937AR_H) $(LIBCONFIG_H) $(YAML_CPP_H)
 	@echo "	CC	$<"
-	@@CC@ @CFLAGS@ $(COMMON_INCLUDE) $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+	@@CC@ @CFLAGS@ $(COMMON_INCLUDE) $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) $(YAML_CPP_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
 	
-obj/%.o: %.cpp $(MAP_H) $(COMMON_H)  $(MT19937AR_H) $(LIBCONFIG_H)
+obj/%.o: %.cpp $(MAP_H) $(COMMON_H)  $(MT19937AR_H) $(LIBCONFIG_H) $(YAML_CPP_H)
 	@echo "	CXX	$<"
-	@@CXX@ @CXXFLAGS@ $(COMMON_INCLUDE) $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+	@@CXX@ @CXXFLAGS@ $(COMMON_INCLUDE) $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) $(YAML_CPP_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
 
 # missing object files
 $(COMMON_AR):
@@ -91,3 +97,6 @@ $(MT19937AR_OBJ):
 
 $(LIBCONFIG_AR):
 	@$(MAKE) -C ../../3rdparty/libconfig
+
+$(YAML_CPP_AR):
+	@$(MAKE) -C ../../3rdparty/yaml-cpp

+ 1268 - 0
src/map/achievement.c

@@ -0,0 +1,1268 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/cbasetypes.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+#include "../common/strlib.h"
+#include "../common/utils.h"
+#include "../common/yamlwrapper.h"
+
+#include "achievement.h"
+#include "chrif.h"
+#include "clif.h"
+#include "intif.h"
+#include "itemdb.h"
+#include "map.h"
+#include "pc.h"
+#include "script.h"
+#include "status.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <setjmp.h>
+
+static jmp_buf     av_error_jump;
+static char*       av_error_msg;
+static const char* av_error_pos;
+static int         av_error_report;
+
+static DBMap *achievement_db = NULL; // int achievement_id -> struct achievement_db *
+static DBMap *achievementmobs_db = NULL; // Avoids checking achievements on every mob killed
+static void achievement_db_free_sub(struct achievement_db *achievement, bool free);
+
+/**
+ * Searches an achievement by ID
+ * @param achievement_id: ID to lookup
+ * @return Achievement entry (equals to &achievement_dummy if the ID is invalid)
+ */
+struct achievement_db *achievement_search(int achievement_id)
+{
+	struct achievement_db *achievement = (struct achievement_db *)idb_get(achievement_db, achievement_id);
+
+	if (!achievement)
+		return &achievement_dummy;
+	return achievement;
+}
+
+/**
+ * Searches for an achievement by monster ID
+ * @param mob_id: Monster ID to lookup
+ * @return True on success, false on failure
+ */
+bool achievement_mobexists(int mob_id)
+{
+	if (!battle_config.feature_achievement)
+		return false;
+	return idb_exists(achievementmobs_db, mob_id);
+}
+
+/**
+ * Add an achievement to the player's log
+ * @param sd: Player data
+ * @param achievement_id: Achievement to add
+ * @return NULL on failure, achievement data on success
+ */
+struct achievement *achievement_add(struct map_session_data *sd, int achievement_id)
+{
+	struct achievement_db *adb = &achievement_dummy;
+	int i, index;
+
+	nullpo_retr(NULL, sd);
+
+	if ((adb = achievement_search(achievement_id)) == &achievement_dummy) {
+		ShowError("achievement_add: Achievement %d not found in DB.\n", achievement_id);
+		return NULL;
+	}
+
+	ARR_FIND(0, sd->achievement_data.count, i, sd->achievement_data.achievements[i].achievement_id == achievement_id);
+	if (i < sd->achievement_data.count) {
+		ShowError("achievement_add: Character %d already has achievement %d.\n", sd->status.char_id, achievement_id);
+		return NULL;
+	}
+
+	index = sd->achievement_data.incompleteCount;
+
+	sd->achievement_data.count++;
+	sd->achievement_data.incompleteCount++;
+	RECREATE(sd->achievement_data.achievements, struct achievement, sd->achievement_data.count);
+
+	// The character has some completed achievements, make room before them so that they will stay at the end of the array
+	if (sd->achievement_data.incompleteCount != sd->achievement_data.count)
+		memmove(&sd->achievement_data.achievements[index + 1], &sd->achievement_data.achievements[index], sizeof(struct achievement) * (sd->achievement_data.count - sd->achievement_data.incompleteCount));
+
+	memset(&sd->achievement_data.achievements[index], 0, sizeof(struct achievement));
+
+	sd->achievement_data.achievements[index].achievement_id = achievement_id;
+	sd->achievement_data.achievements[index].score = adb->score;
+	sd->achievement_data.save = true;
+
+	clif_achievement_update(sd, &sd->achievement_data.achievements[index], sd->achievement_data.count - sd->achievement_data.incompleteCount);
+
+	return &sd->achievement_data.achievements[index];
+}
+
+/**
+ * Removes an achievement from a player's log
+ * @param sd: Player's data
+ * @param achievement_id: Achievement to remove
+ * @return True on success, false on failure
+ */
+bool achievement_remove(struct map_session_data *sd, int achievement_id)
+{
+	struct achievement dummy;
+	int i;
+
+	nullpo_retr(false, sd);
+
+	if (achievement_search(achievement_id) == &achievement_dummy) {
+		ShowError("achievement_delete: Achievement %d not found in DB.\n", achievement_id);
+		return false;
+	}
+
+	ARR_FIND(0, sd->achievement_data.count, i, sd->achievement_data.achievements[i].achievement_id == achievement_id);
+	if (i == sd->achievement_data.count) {
+		ShowError("achievement_delete: Character %d doesn't have achievement %d.\n", sd->status.char_id, achievement_id);
+		return false;
+	}
+
+	if (i != sd->achievement_data.count - 1)
+		memmove(&sd->achievement_data.achievements[i], &sd->achievement_data.achievements[i + 1], sizeof(struct achievement) * (sd->achievement_data.count - 1 - i));
+
+	sd->achievement_data.count--;
+	if (!sd->achievement_data.achievements[i].completed)
+		sd->achievement_data.incompleteCount--;
+	RECREATE(sd->achievement_data.achievements, struct achievement, sd->achievement_data.count);
+	sd->achievement_data.save = true;
+
+	// Send a removed fake achievement
+	memset(&dummy, 0, sizeof(struct achievement));
+	dummy.achievement_id = achievement_id;
+	clif_achievement_update(sd, &dummy, sd->achievement_data.count - sd->achievement_data.incompleteCount);
+
+	return true;
+}
+
+/**
+ * Checks to see if an achievement has a dependent, and if so, checks if that dependent is complete
+ * @param sd: Player data
+ * @param achievement_id: Achievement to check if it has a dependent
+ * @return False on failure or not complete, true on complete or no dependents
+ */
+bool achievement_check_dependent(struct map_session_data *sd, int achievement_id)
+{
+	struct achievement_db *adb = &achievement_dummy;
+
+	nullpo_retr(false, sd);
+
+	adb = achievement_search(achievement_id);
+
+	if (adb == &achievement_dummy)
+		return false;
+
+	// Check if the achievement has a dependent
+	// If so, then do a check on all dependents to see if they're complete
+	if (adb->dependent_count) {
+		int i;
+
+		for (i = 0; i < adb->dependent_count; i++) {
+			struct achievement_db *adb_dep = achievement_search(adb->dependents[i].achievement_id);
+			int j;
+
+			if (adb_dep == &achievement_dummy)
+				return false;
+
+			ARR_FIND(0, sd->achievement_data.count, j, sd->achievement_data.achievements[j].achievement_id == adb->dependents[i].achievement_id && sd->achievement_data.achievements[j].completed > 0);
+			if (j == sd->achievement_data.count)
+				return false; // One of the dependent is not complete!
+		}
+	}
+
+	return true;
+}
+
+/**
+ * Check achievements that only have dependents and no other requirements
+ * @return True if successful, false if not
+ */
+static int achievement_check_groups(DBKey key, DBData *data, va_list ap)
+{
+	struct achievement_db *ad;
+	struct map_session_data *sd;
+	int i;
+
+	ad = (struct achievement_db *)db_data2ptr(data);
+	sd = va_arg(ap, struct map_session_data *);
+
+	if (ad == &achievement_dummy || sd == NULL)
+		return 0;
+
+	if (ad->group != AG_BATTLE && ad->group != AG_TAMING && ad->group != AG_ADVENTURE)
+		return 0;
+
+	if (ad->dependent_count == 0 || ad->condition)
+		return 0;
+
+	ARR_FIND(0, sd->achievement_data.count, i, sd->achievement_data.achievements[i].achievement_id == ad->achievement_id);
+	if (i == sd->achievement_data.count) { // Achievment isn't in player's log
+		if (achievement_check_dependent(sd, ad->achievement_id) == true) {
+			achievement_add(sd, ad->achievement_id);
+			achievement_update_achievement(sd, ad->achievement_id, true);
+		}
+	}
+
+	return 1;
+}
+
+/**
+ * Update an achievement
+ * @param sd: Player to update
+ * @param achievement_id: Achievement ID of the achievement to update
+ * @param complete: Complete state of an achievement
+ * @return True if successful, false if not
+ */
+bool achievement_update_achievement(struct map_session_data *sd, int achievement_id, bool complete)
+{
+	struct achievement_db *adb = &achievement_dummy;
+	int i;
+
+	nullpo_retr(false, sd);
+
+	adb = achievement_search(achievement_id);
+
+	if (adb == &achievement_dummy)
+		return false;
+
+	ARR_FIND(0, sd->achievement_data.incompleteCount, i, sd->achievement_data.achievements[i].achievement_id == achievement_id);
+	if (i == sd->achievement_data.incompleteCount)
+		return false;
+
+	if (sd->achievement_data.achievements[i].completed > 0)
+		return false;
+
+	// Finally we send the updated achievement to the client
+	if (complete) {
+		if (adb->target_count) { // Make sure all the objective targets are at their respective total requirement
+			int k;
+
+			for (k = 0; k < adb->target_count; k++)
+				sd->achievement_data.achievements[i].count[k] = adb->targets[k].count;
+
+			for (k = 1; k < adb->dependent_count; k++) {
+				sd->achievement_data.achievements[i].count[k] = max(1, sd->achievement_data.achievements[i].count[k]);
+			}
+		}
+
+		sd->achievement_data.achievements[i].completed = time(NULL);
+
+		if (i < (--sd->achievement_data.incompleteCount)) { // The achievement needs to be moved to the completed achievements block at the end of the array
+			struct achievement tmp_ach;
+
+			memcpy(&tmp_ach, &sd->achievement_data.achievements[i], sizeof(struct achievement));
+			memcpy(&sd->achievement_data.achievements[i], &sd->achievement_data.achievements[sd->achievement_data.incompleteCount], sizeof(struct achievement));
+			memcpy(&sd->achievement_data.achievements[sd->achievement_data.incompleteCount], &tmp_ach, sizeof(struct achievement));
+		}
+
+		achievement_level(sd, true); // Re-calculate achievement level
+		// Check dependents
+		achievement_db->foreach(achievement_db, achievement_check_groups, sd);
+		ARR_FIND(sd->achievement_data.incompleteCount, sd->achievement_data.count, i, sd->achievement_data.achievements[i].achievement_id == achievement_id); // Look for the index again, the position most likely changed
+	}
+
+	clif_achievement_update(sd, &sd->achievement_data.achievements[i], sd->achievement_data.count - sd->achievement_data.incompleteCount);
+	sd->achievement_data.save = true; // Flag to save with the autosave interval
+
+	if (sd->achievement_data.sendlist) {
+		clif_achievement_list_all(sd);
+		sd->achievement_data.sendlist = false;
+	}
+
+	return true;
+}
+
+/**
+ * Get the reward of an achievement
+ * @param sd: Player getting the reward
+ * @param achievement_id: Achievement to get reward data
+ */
+void achievement_get_reward(struct map_session_data *sd, int achievement_id, time_t rewarded)
+{
+	struct achievement_db *adb = achievement_search(achievement_id);
+	int i;
+
+	nullpo_retv(sd);
+
+	if( rewarded == 0 ){
+		clif_achievement_reward_ack(sd->fd, 0, achievement_id);
+		return;
+	}
+
+	if (adb == &achievement_dummy) {
+		ShowError("achievement_reward: Inter server sent a reward claim for achievement %d not found in DB.\n", achievement_id);
+		return;
+	}
+
+	ARR_FIND(0, sd->achievement_data.count, i, sd->achievement_data.achievements[i].achievement_id == achievement_id);
+
+	if (i == sd->achievement_data.count) {
+		return;
+	}
+
+	// Only update in the cache, db was updated already
+	sd->achievement_data.achievements[i].rewarded = rewarded;
+
+	run_script(adb->rewards.script, 0, sd->bl.id, fake_nd->bl.id);
+	if (adb->rewards.title_id) {
+		RECREATE(sd->titles, int, sd->titleCount + 1);
+		sd->titles[sd->titleCount] = adb->rewards.title_id;
+		sd->titleCount++;
+		sd->achievement_data.sendlist = true;
+	}
+
+	clif_achievement_reward_ack(sd->fd, 1, achievement_id);
+	clif_achievement_update(sd, &sd->achievement_data.achievements[i], sd->achievement_data.count - sd->achievement_data.incompleteCount);
+}
+
+/**
+ * Check if player has recieved an achievement's reward
+ * @param sd: Player to get reward
+ * @param achievement_id: Achievement to get reward data
+ */
+void achievement_check_reward(struct map_session_data *sd, int achievement_id)
+{
+	int i;
+	struct achievement_db *adb = achievement_search(achievement_id);
+
+	nullpo_retv(sd);
+
+	if (adb == &achievement_dummy) {
+		ShowError("achievement_reward: Trying to reward achievement %d not found in DB.\n", achievement_id);
+		clif_achievement_reward_ack(sd->fd, 0, achievement_id);
+		return;
+	}
+
+	ARR_FIND(0, sd->achievement_data.count, i, sd->achievement_data.achievements[i].achievement_id == achievement_id);
+	if (i == sd->achievement_data.count) {
+		clif_achievement_reward_ack(sd->fd, 0, achievement_id);
+		return;
+	}
+
+	if (sd->achievement_data.achievements[i].rewarded > 0 || sd->achievement_data.achievements[i].completed == 0) {
+		clif_achievement_reward_ack(sd->fd, 0, achievement_id);
+		return;
+	}
+
+	if( !intif_achievement_reward(sd,adb) ){
+		clif_achievement_reward_ack(sd->fd, 0, achievement_id);
+	}
+}
+
+/**
+ * Return all titles to a player based on completed achievements
+ * @param char_id: Character ID requesting
+ */
+void achievement_get_titles(uint32 char_id)
+{
+	struct map_session_data *sd = map_charid2sd(char_id);
+
+	if (sd) {
+		sd->titles = NULL;
+		sd->titleCount = 0;
+
+		if (sd->achievement_data.count) {
+			int i;
+
+			for (i = 0; i < sd->achievement_data.count; i++) {
+				struct achievement_db *adb = achievement_search(sd->achievement_data.achievements[i].achievement_id);
+
+				if (adb && adb->rewards.title_id && sd->achievement_data.achievements[i].completed > 0) { // If the achievement has a title and is complete, give it to the player
+					RECREATE(sd->titles, int, sd->titleCount + 1);
+					sd->titles[sd->titleCount] = adb->rewards.title_id;
+					sd->titleCount++;
+				}
+			}
+		}
+	}
+}
+
+/**
+ * Frees the player's data for achievements and titles
+ * @param sd: Player's session
+ */
+void achievement_free(struct map_session_data *sd)
+{
+	nullpo_retv(sd);
+
+	if (sd->titleCount) {
+		aFree(sd->titles);
+		sd->titles = NULL;
+		sd->titleCount = 0;
+	}
+
+	if (sd->achievement_data.count) {
+		aFree(sd->achievement_data.achievements);
+		sd->achievement_data.achievements = NULL;
+		sd->achievement_data.count = sd->achievement_data.incompleteCount = 0;
+	}
+}
+
+/**
+ * Get an achievement's progress information
+ * @param sd: Player to check achievement progress
+ * @param achievement_id: Achievement progress to check
+ * @param type: Type to return
+ * @return The type's data, -1 if player doesn't have achievement, -2 on failure/incorrect type
+ */
+int achievement_check_progress(struct map_session_data *sd, int achievement_id, int type)
+{
+	int i;
+
+	nullpo_retr(-2, sd);
+
+	// Achievement ID is not needed so skip the lookup
+	if (type == ACHIEVEINFO_LEVEL)
+		return sd->achievement_data.level;
+	else if (type == ACHIEVEINFO_SCORE)
+		return sd->achievement_data.total_score;
+
+	ARR_FIND(0, sd->achievement_data.count, i, sd->achievement_data.achievements[i].achievement_id == achievement_id);
+	if (i == sd->achievement_data.count)
+		return -1;
+
+	if (type >= ACHIEVEINFO_COUNT1 && type <= ACHIEVEINFO_COUNT10)
+		return sd->achievement_data.achievements[i].count[type - 1];
+	else if (type == ACHIEVEINFO_COMPLETE)
+		return sd->achievement_data.achievements[i].completed > 0;
+	else if (type == ACHIEVEINFO_COMPLETEDATE)
+		return (int)sd->achievement_data.achievements[i].completed;
+	else if (type == ACHIEVEINFO_GOTREWARD)
+		return sd->achievement_data.achievements[i].rewarded > 0;
+	return -2;
+}
+
+/**
+ * Calculate a player's achievement level
+ * @param sd: Player to check achievement level
+ * @param flag: If the call should attempt to give the AG_GOAL_ACHIEVE achievement
+ */
+int *achievement_level(struct map_session_data *sd, bool flag)
+{
+	static int info[2];
+	int i, old_level;
+	const int score_table[MAX_ACHIEVEMENT_RANK] = { 18, 31, 49, 73, 135, 104, 140, 178, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000 }; //! TODO: Figure out the EXP required to level up from 8-20
+
+	nullpo_retr(0, sd);
+
+	sd->achievement_data.total_score = 0;
+	old_level = sd->achievement_data.level;
+
+	for (i = 0; i < sd->achievement_data.count; i++) {
+		if (sd->achievement_data.achievements[i].completed > 0)
+			sd->achievement_data.total_score += sd->achievement_data.achievements[i].score;
+	}
+
+	info[0] = 0;
+	info[1] = 0;
+
+	for (i = 0; i < MAX_ACHIEVEMENT_RANK; i++) {
+		info[0] = info[1];
+			
+		if (i < ARRAYLENGTH(score_table))
+			info[1] = score_table[i];
+		else {
+			info[0] = info[1];
+			info[1] = info[1] + 500;
+		}
+
+		if (sd->achievement_data.total_score < info[1])
+			break;
+	}
+
+	if (i == MAX_ACHIEVEMENT_RANK)
+		i = 0;
+
+	info[1] = info[1] - info[0]; // Right number
+	info[0] = sd->achievement_data.total_score - info[0]; // Left number
+	sd->achievement_data.level = i;
+
+	if (flag == true && old_level != sd->achievement_data.level) {
+		int achievement_id = 240000 + sd->achievement_data.level;
+
+		achievement_add(sd, achievement_id);
+		achievement_update_achievement(sd, achievement_id, true);
+	}
+
+	return info;
+}
+
+/**
+ * Update achievement objectives.
+ * @see DBApply
+ */
+static int achievement_update_objectives(DBKey key, DBData *data, va_list ap)
+{
+	struct achievement_db *ad;
+	struct map_session_data *sd;
+	enum e_achievement_group group;
+	struct achievement *entry = NULL;
+	bool isNew = false, changed = false, complete = false;
+	int i, k = 0, objective_count[MAX_ACHIEVEMENT_OBJECTIVES], update_count[MAX_ACHIEVEMENT_OBJECTIVES];
+
+	ad = (struct achievement_db *)db_data2ptr(data);
+	sd = va_arg(ap, struct map_session_data *);
+	group = (enum e_achievement_group)va_arg(ap, int);
+	memcpy(update_count, (int *)va_arg(ap, int *), sizeof(update_count));
+
+	if (ad == NULL || sd == NULL)
+		return 0;
+
+	if (group <= AG_NONE || group >= AG_MAX)
+		return 0;
+
+	if (group != ad->group)
+		return 0;
+
+	memset(objective_count, 0, sizeof(objective_count)); // Current objectives count
+
+	ARR_FIND(0, sd->achievement_data.count, i, sd->achievement_data.achievements[i].achievement_id == ad->achievement_id);
+	if (i == sd->achievement_data.count) { // Achievment isn't in player's log
+		if (achievement_check_dependent(sd, ad->achievement_id) == false) // Check to see if dependents are complete before adding to player's log
+			return 0;
+		isNew = true;
+	} else {
+		entry = &sd->achievement_data.achievements[i];
+
+		if (entry->completed > 0) // Player has completed the achievement
+			return 0;
+
+		memcpy(objective_count, entry->count, sizeof(objective_count));
+	}
+
+	switch (group) {
+		case AG_ADD_FRIEND:
+		case AG_BABY:
+		case AG_CHAT_COUNT:
+		case AG_CHAT_CREATE:
+		case AG_CHAT_DYING:
+		case AG_GET_ITEM:
+		case AG_GET_ZENY:
+		case AG_GOAL_LEVEL:
+		case AG_GOAL_STATUS:
+		case AG_JOB_CHANGE:
+		case AG_MARRY:
+		case AG_PARTY:
+		case AG_REFINE_FAIL:
+		case AG_REFINE_SUCCESS:
+		case AG_SPEND_ZENY:
+			if (group == AG_SPEND_ZENY) { // Achievement type is cummulative
+				objective_count[0] += update_count[0];
+				changed = true;
+			}
+
+			if (!ad->condition || achievement_check_condition(ad->condition, sd, update_count)) {
+				changed = true;
+				complete = true;
+			}
+
+			if (changed == false)
+				break;
+
+			if (isNew) {
+				if ((entry = achievement_add(sd, ad->achievement_id)) == NULL)
+					return 0; // Failed to add achievement, fall out
+			}
+			break;
+		case AG_CHAT:
+			if (!ad->target_count)
+				break;
+
+			if (ad->condition && !achievement_check_condition(ad->condition, sd, update_count)) // Parameters weren't met
+				break;
+
+			if (ad->mapindex > -1 && sd->bl.m != ad->mapindex)
+				break;
+
+			for (i = 0; i < ad->target_count; i++) {
+				if (objective_count[i] < ad->targets[i].count)
+					objective_count[i] += update_count[0];
+			}
+
+			changed = true;
+
+			ARR_FIND(0, ad->target_count, k, objective_count[k] < ad->targets[k].count);
+			if (k == ad->target_count)
+				complete = true;
+
+			if (isNew) {
+				if ((entry = achievement_add(sd, ad->achievement_id)) == NULL)
+					return 0; // Failed to add achievement, fall out
+			}
+			break;
+		case AG_BATTLE:
+		case AG_TAMING:
+			ARR_FIND(0, ad->target_count, k, ad->targets[k].mob == update_count[0]);
+			if (k == ad->target_count)
+				break; // Mob wasn't found
+
+			for (k = 0; k < ad->target_count; k++) {
+				if (ad->targets[k].mob == update_count[0] && objective_count[k] < ad->targets[k].count) {
+					objective_count[k]++;
+					changed = true;
+				}
+			}
+
+			ARR_FIND(0, ad->target_count, k, objective_count[k] < ad->targets[k].count);
+			if (k == ad->target_count)
+				complete = true;
+
+			if (isNew) {
+				if ((entry = achievement_add(sd, ad->achievement_id)) == NULL)
+					return 0; // Failed to add achievement, fall out
+			}
+			break;
+	}
+
+	if (changed) {
+		memcpy(entry->count, objective_count, sizeof(objective_count));
+		achievement_update_achievement(sd, ad->achievement_id, complete);
+	}
+
+	return 1;
+}
+
+/**
+ * Update achievement objective count.
+ * @param sd: Player data
+ * @param group: Achievement enum type
+ * @param sp_value: SP parameter value
+ * @param arg_count: va_arg count
+ */
+void achievement_update_objective(struct map_session_data *sd, enum e_achievement_group group, uint8 arg_count, ...)
+{
+	if (sd) {
+		va_list ap;
+		int i, count[MAX_ACHIEVEMENT_OBJECTIVES];
+
+		if (!battle_config.feature_achievement)
+			return;
+
+		memset(count, 0, sizeof(count)); // Clear out array before setting values
+
+		va_start(ap, arg_count);
+		for (i = 0; i < arg_count; i++)
+			count[i] = va_arg(ap, int);
+		va_end(ap);
+
+		switch(group) {
+			case AG_CHAT: //! TODO: Not sure how this works officially
+			case AG_GOAL_ACHIEVE:
+				// These have no objective use right now.
+				break;
+			default:
+				achievement_db->foreach(achievement_db, achievement_update_objectives, sd, (int)group, count);
+				break;
+		}
+	}
+}
+
+/*==========================================
+ * Achievement condition parsing section
+ *------------------------------------------*/
+static void disp_error_message2(const char *mes,const char *pos,int report)
+{
+	av_error_msg = aStrdup(mes);
+	av_error_pos = pos;
+	av_error_report = report;
+	longjmp(av_error_jump, 1);
+}
+#define disp_error_message(mes,pos) disp_error_message2(mes,pos,1)
+
+/**
+ * Checks the condition of an achievement.
+ * @param condition: Achievement condition
+ * @param sd: Player data
+ * @param count: Script arguments
+ * @return The result of the condition.
+ */
+long long achievement_check_condition(struct av_condition *condition, struct map_session_data *sd, int *count)
+{
+	long long left = 0;
+	long long right = 0;
+
+	// Reduce the recursion, almost all calls will be C_PARAM, C_NAME or C_ARG
+	if (condition->left) {
+		if (condition->left->op == C_NAME || condition->left->op == C_INT)
+			left = condition->left->value;
+		else if (condition->left->op == C_PARAM)
+			left = pc_readparam(sd, (int)condition->left->value);
+		else if (condition->left->op == C_ARG && condition->left->value < MAX_ACHIEVEMENT_OBJECTIVES)
+			left = count[condition->left->value];
+		else
+			left = achievement_check_condition(condition->left, sd, count);
+	}
+
+	if (condition->right) {
+		if (condition->right->op == C_NAME || condition->right->op == C_INT)
+			right = condition->right->value;
+		else if (condition->right->op == C_PARAM)
+			right = pc_readparam(sd, (int)condition->right->value);
+		else if (condition->right->op == C_ARG && condition->right->value < MAX_ACHIEVEMENT_OBJECTIVES)
+			right = count[condition->right->value];
+		else
+			right = achievement_check_condition(condition->right, sd, count);
+	}
+
+	switch(condition->op) {
+		case C_NOP:
+			return false;
+		case C_NAME:
+		case C_INT:
+			return condition->value;
+		case C_PARAM:
+			return pc_readparam(sd, (int)condition->value);
+		case C_LOR: 
+			return left || right;
+		case C_LAND:
+			return left && right;
+		case C_LE:
+			return left <= right;
+		case C_LT:
+			return left < right;
+		case C_GE:
+			return left >= right;
+		case C_GT:
+			return left > right;
+		case C_EQ:
+			return left == right;
+		case C_NE:
+			return left != right;
+		case C_XOR:
+			return left ^ right;
+		case C_OR:
+			return left || right;
+		case C_AND:
+			return left & right;
+		case C_ADD:
+			return left + right;
+		case C_SUB:
+			return left - right;
+		case C_MUL:
+			return left * right;
+		case C_DIV:
+			return left / right;
+		case C_MOD:
+			return left % right;
+		case C_NEG:
+			return -left;
+		case C_LNOT:
+			return !left;
+		case C_NOT:
+			return ~left;
+		case C_R_SHIFT:
+			return left >> right;
+		case C_L_SHIFT:
+			return left << right;
+		case C_ARG:
+			if (condition->value < MAX_ACHIEVEMENT_OBJECTIVES)
+				return count[condition->value];
+
+			return false;
+		default:
+			ShowError("achievement_check_condition: unexpected operator: %d\n", condition->op);
+			return false;
+	}
+
+	return false;
+}
+
+static const char *skip_word(const char *p)
+{
+	while (ISALNUM(*p) || *p == '_')
+		++p;
+
+	if (*p == '$') // String
+		p++;
+
+	return p;
+}
+
+const char *av_parse_simpleexpr(const char *p, struct av_condition *parent)
+{
+	long long i;
+
+	p = skip_space(p);
+
+	if(*p == ';' || *p == ',')
+		disp_error_message("av_parse_simpleexpr: unexpected character.", p);
+	if(*p == '(') {
+		p = av_parse_subexpr(p + 1, -1, parent);
+		p = skip_space(p);
+
+		if (*p != ')')
+			disp_error_message("av_parse_simpleexpr: unmatched ')'", p);
+		++p;
+	} else if(is_number(p)) {
+		char *np;
+
+		while(*p == '0' && ISDIGIT(p[1]))
+			p++;
+		i = strtoll(p, &np, 0);
+
+		if (i < INT_MIN) {
+			i = INT_MIN;
+			disp_error_message("av_parse_simpleexpr: underflow detected, capping value to INT_MIN.", p);
+		} else if (i > INT_MAX) {
+			i = INT_MAX;
+			disp_error_message("av_parse_simpleexpr: underflow detected, capping value to INT_MAX.", p);
+		}
+
+		parent->op = C_INT;
+		parent->value = i;
+		p = np;
+	} else {
+		int v, len;
+		char * word;
+
+		if (skip_word(p) == p)
+			disp_error_message("av_parse_simpleexpr: unexpected character.", p);
+
+		len = skip_word(p) - p;
+
+		if (len == 0)
+			disp_error_message("av_parse_simpleexpr: invalid word. A word consists of undercores and/or alphanumeric characters.", p);
+
+		word = (char*)aMalloc(len + 1);
+		memcpy(word, p, len);
+		word[len] = 0;
+
+		if (script_get_parameter(word, &v))
+			parent->op = C_PARAM;
+		else if (script_get_constant(word, &v)) {
+			if (word[0] == 'b' && ISUPPER(word[1])) // Consider b* variables as parameters (because they... are?)
+				parent->op = C_PARAM;
+			else
+				parent->op = C_NAME;
+		} else {
+			if (word[0] == 'A' && word[1] == 'R' && word[2] == 'G' && ISDIGIT(word[3])) { // Special constants used to set temporary variables
+				parent->op = C_ARG;
+				v = atoi(word + 3);
+			} else {
+				aFree(word);
+				disp_error_message("av_parse_simpleexpr: invalid constant.", p);
+			}
+		}
+
+		aFree(word);
+		parent->value = v;
+		p = skip_word(p);
+	}
+
+	return p;
+}
+
+const char* av_parse_subexpr(const char* p, int limit, struct av_condition *parent)
+{
+	int op, opl, len;
+
+	p = skip_space(p);
+
+	CREATE(parent->left, struct av_condition, 1);
+
+	if ((op = C_NEG, *p == '-') || (op = C_LNOT, *p == '!') || (op = C_NOT, *p == '~')) { // Unary - ! ~ operators
+		p = av_parse_subexpr(p + 1, 11, parent->left);
+		parent->op = op;
+	} else
+		p = av_parse_simpleexpr(p, parent->left);
+
+	p = skip_space(p);
+
+	while((
+			(op=C_ADD,opl=9,len=1,*p=='+') ||
+			(op=C_SUB,opl=9,len=1,*p=='-') ||
+			(op=C_MUL,opl=10,len=1,*p=='*') ||
+			(op=C_DIV,opl=10,len=1,*p=='/') ||
+			(op=C_MOD,opl=10,len=1,*p=='%') ||
+			(op=C_LAND,opl=2,len=2,*p=='&' && p[1]=='&') ||
+			(op=C_AND,opl=5,len=1,*p=='&') ||
+			(op=C_LOR,opl=1,len=2,*p=='|' && p[1]=='|') ||
+			(op=C_OR,opl=3,len=1,*p=='|') ||
+			(op=C_XOR,opl=4,len=1,*p=='^') ||
+			(op=C_EQ,opl=6,len=2,*p=='=' && p[1]=='=') ||
+			(op=C_NE,opl=6,len=2,*p=='!' && p[1]=='=') ||
+			(op=C_R_SHIFT,opl=8,len=2,*p=='>' && p[1]=='>') ||
+			(op=C_GE,opl=7,len=2,*p=='>' && p[1]=='=') ||
+			(op=C_GT,opl=7,len=1,*p=='>') ||
+			(op=C_L_SHIFT,opl=8,len=2,*p=='<' && p[1]=='<') ||
+			(op=C_LE,opl=7,len=2,*p=='<' && p[1]=='=') ||
+			(op=C_LT,opl=7,len=1,*p=='<')) && opl>limit) {
+		p += len;
+
+		if (parent->right) { // Chain conditions
+			struct av_condition *condition = NULL;
+			CREATE(condition, struct av_condition, 1);
+			condition->op = parent->op;
+			condition->left = parent->left;
+			condition->right = parent->right;
+			parent->left = condition;
+			parent->right = NULL;
+		}
+
+		CREATE(parent->right, struct av_condition, 1);
+		p = av_parse_subexpr(p, opl, parent->right);
+		parent->op = op;
+		p = skip_space(p);
+	}
+
+	if (parent->op == C_NOP && parent->right == NULL) { // Move the node up
+		struct av_condition *temp = parent->left;
+
+		parent->right = parent->left->right;
+		parent->op = parent->left->op;
+		parent->value = parent->left->value;
+		parent->left = parent->left->left;
+
+		aFree(temp);
+	}
+
+	return p;
+}
+
+/**
+ * Parses a condition from a script.
+ * @param p: The script buffer.
+ * @param file: The file being parsed.
+ * @param line: The current achievement line number.
+ * @return The parsed achievement condition.
+ */
+struct av_condition *parse_condition(const char *p, const char *file, int line)
+{
+	struct av_condition *condition = NULL;
+
+	if (setjmp(av_error_jump) != 0) {
+		if (av_error_report)
+			script_error(p,file,line,av_error_msg,av_error_pos);
+		aFree(av_error_msg);
+		if (condition)
+			achievement_script_free(condition);
+		return NULL;
+	}
+
+	switch(*p) {
+		case ')': case ';': case ':': case '[': case ']': case '}':
+			disp_error_message("parse_condition: unexpected character.", p);
+	}
+
+	condition = (struct av_condition *) aCalloc(1, sizeof(struct av_condition));
+	av_parse_subexpr(p, -1, condition);
+
+	return condition;
+}
+
+/**
+ * Reads and parses an entry from the achievement_db.
+ * @param wrapper: The YAML wrapper containing the entry.
+ * @param n: The sequential index of the current entry.
+ * @param source: The source YAML file.
+ * @return The parsed achievement entry or NULL in case of error.
+ */
+struct achievement_db *achievement_read_db_sub(yamlwrapper *wrapper, int n, const char *source)
+{
+	struct achievement_db *entry = NULL;
+	yamlwrapper *t = NULL;
+	yamliterator *it;
+	enum e_achievement_group group = AG_NONE;
+	int score = 0, achievement_id = 0;
+	char *group_char = NULL, *name = NULL, *condition = NULL, *mapname = NULL;
+
+	if (!yaml_node_is_defined(wrapper, "ID")) {
+		ShowWarning("achievement_read_db_sub: Missing ID in \"%s\", entry #%d, skipping.\n", source, n);
+		return NULL;
+	} else
+		achievement_id = yaml_get_int(wrapper, "ID");
+	if (achievement_id < 1 || achievement_id > INT_MAX) {
+		ShowWarning("achievement_read_db_sub: Invalid achievement ID %d in \"%s\", entry #%d (min: 1, max: %d), skipping.\n", achievement_id, source, n, INT_MAX);
+		return NULL;
+	}
+
+	if (!yaml_node_is_defined(wrapper, "Group")) {
+		ShowWarning("achievement_read_db_sub: Missing group for achievement %d in \"%s\", skipping.\n", achievement_id, source);
+		return NULL;
+	} else
+		group_char = yaml_get_c_string(wrapper, "Group");
+	if (!script_get_constant(group_char, (int *)&group)) {
+		ShowWarning("achievement_read_db_sub: Invalid group %s for achievement %d in \"%s\", skipping.\n", group_char, achievement_id, source);
+		return NULL;
+	}
+	aFree(group_char);
+
+	if (!yaml_node_is_defined(wrapper, "Name")) {
+		ShowWarning("achievement_read_db_sub: Missing achievement name for achievement %d in \"%s\", skipping.\n", name, achievement_id, source);
+		return NULL;
+	} else
+		name = yaml_get_c_string(wrapper, "Name");
+
+	CREATE(entry, struct achievement_db, 1);
+	entry->achievement_id = achievement_id;
+	entry->group = group;
+	safestrncpy(entry->name, name, sizeof(entry->name));
+	aFree(name);
+	entry->mapindex = -1;
+
+	if (yaml_node_is_defined(wrapper, "Target") && (t = yaml_get_subnode(wrapper, "Target")) && (it = yaml_get_iterator(t)) && yaml_iterator_is_valid(it)) {
+		yamlwrapper *tt = NULL;
+
+		for (tt = yaml_iterator_first(it); yaml_iterator_has_next(it) && entry->target_count < MAX_ACHIEVEMENT_OBJECTIVES; tt = yaml_iterator_next(it)) {
+			int mobid = 0, count = 0;
+
+			if (yaml_node_is_defined(tt, "MobID") && (mobid = yaml_get_int(tt, "MobID")) && !mobdb_exists(mobid)) { // The mob ID field is not required
+				ShowError("achievement_read_db_sub: Invalid mob ID %d for achievement %d in \"%s\", skipping.\n", mobid, achievement_id, source);
+				continue;
+			}
+			if (yaml_node_is_defined(tt, "Count") && (!(count = yaml_get_int(tt, "Count")) || count <= 0)) {
+				ShowError("achievement_read_db_sub: Invalid count %d for achievement %d in \"%s\", skipping.\n", count, achievement_id, source);
+				continue;
+			}
+			if (mobid && group == AG_BATTLE && !idb_exists(achievementmobs_db, mobid)) {
+				struct achievement_mob *entrymob = NULL;
+
+				CREATE(entrymob, struct achievement_mob, 1);
+				idb_put(achievementmobs_db, mobid, entrymob);
+			}
+
+			RECREATE(entry->targets, struct achievement_target, entry->target_count + 1);
+			entry->targets[entry->target_count].mob = mobid;
+			entry->targets[entry->target_count].count = count;
+			entry->target_count++;
+			yaml_destroy_wrapper(tt);
+		}
+		yaml_iterator_destroy(it);
+	}
+
+	if (yaml_node_is_defined(wrapper, "Condition") && (condition = yaml_get_c_string(wrapper, "Condition"))){
+		entry->condition = parse_condition(condition, source, n);
+		aFree(condition);
+	}
+
+	if (yaml_node_is_defined(wrapper, "Map") && (mapname = yaml_get_c_string(wrapper, "Map"))) {
+		if (group != AG_CHAT)
+			ShowWarning("achievement_read_db_sub: The map argument can only be used with the group AG_CHATTING (achievement %d in \"%s\"), skipping.\n", achievement_id, source);
+		else {
+			entry->mapindex = map_mapname2mapid(mapname);
+
+			if (entry->mapindex == -1)
+				ShowWarning("achievement_read_db_sub: Invalid map name %s for achievement %d in \"%s\".\n", mapname, achievement_id, source);
+		}
+		aFree(mapname);
+	}
+
+	if (yaml_node_is_defined(wrapper, "Dependent") && (t = yaml_get_subnode(wrapper, "Dependent")) && (it = yaml_get_iterator(t))) {
+		if (yaml_iterator_is_valid(it)) {
+			yamlwrapper *tt = NULL;
+
+			for (tt = yaml_iterator_first(it); yaml_iterator_has_next(it) && entry->dependent_count < MAX_ACHIEVEMENT_DEPENDENTS; tt = yaml_iterator_next(it)) {
+				RECREATE(entry->dependents, struct achievement_dependent, entry->dependent_count + 1);
+				entry->dependents[entry->dependent_count].achievement_id = yaml_as_int(tt);
+				entry->dependent_count++;
+				yaml_destroy_wrapper(tt);
+			}
+			yaml_iterator_destroy(it);
+		} else
+			ShowWarning("achievement_read_db_sub: Invalid dependent format for achievement %d in \"%s\".\n", achievement_id, source);
+	}
+
+	if (yaml_node_is_defined(wrapper, "Reward") && (t = yaml_get_subnode(wrapper, "Reward"))) {
+		char *script_char = NULL;
+		int nameid = 0, amount = 0, titleid = 0;
+
+		if (yaml_node_is_defined(t, "ItemID") && (nameid = yaml_get_int(t, "ItemID"))) {
+			if (itemdb_exists(nameid)) {
+				entry->rewards.nameid = nameid;
+				entry->rewards.amount = 1; // Default the amount to 1
+			} else if (nameid && !itemdb_exists(nameid)) {
+				ShowWarning("achievement_read_db_sub: Invalid reward item ID %hu for achievement %d in \"%s\". Setting to 0.\n", nameid, achievement_id, source);
+				entry->rewards.nameid = nameid = 0;
+			}
+
+			if (yaml_node_is_defined(t, "Amount") && (amount = yaml_get_int(t, "Amount")) && amount > 0 && nameid)
+				entry->rewards.amount = amount;
+		}
+		if (yaml_node_is_defined(t, "Script") && (script_char = yaml_get_c_string(t, "Script"))){
+			entry->rewards.script = parse_script(script_char, source, achievement_id, SCRIPT_IGNORE_EXTERNAL_BRACKETS);
+			aFree(script_char);
+		}
+		if (yaml_node_is_defined(t, "TitleID") && (titleid = yaml_get_int(t, "TitleID")) && titleid > 0)
+			entry->rewards.title_id = titleid;
+	}
+
+	if ((score = yaml_get_int(wrapper, "Score")) && score > 0)
+		entry->score = score;
+
+	return entry;
+}
+
+/**
+ * Loads achievements from the achievement db.
+ */
+void achievement_read_db(void)
+{
+	yamlwrapper *adb = NULL, *adb_sub = NULL;
+	yamliterator *it;
+	int i = 0;
+	const char *dbsubpath[] = {
+		"",
+		"/"DBIMPORT"/",
+		//add other path here
+	};
+
+	for (i = 0; i < ARRAYLENGTH(dbsubpath); i++) {
+		char filepath[256];
+		int count = 0;
+
+		if (!i)
+			sprintf(filepath, "%s/%s%s%s", db_path, DBPATH, dbsubpath[i], "achievement_db.yml");
+		else
+			sprintf(filepath, "%s%s%s", db_path, dbsubpath[i], "achievement_db.yml");
+
+		if ((adb = yaml_load_file(filepath)) == NULL) {
+			ShowError("Failed to read '%s'.\n", filepath);
+			continue;
+		}
+
+		if (!yaml_node_is_defined(adb, "Achievements"))
+			continue; // Skip if base structure isn't defined
+		adb_sub = yaml_get_subnode(adb, "Achievements");
+		it = yaml_get_iterator(adb_sub);
+		if (yaml_iterator_is_valid(it)) {
+			yamlwrapper *id = NULL;
+
+			for (id = yaml_iterator_first(it); yaml_iterator_has_next(it); id = yaml_iterator_next(it)) {
+				struct achievement_db *duplicate = &achievement_dummy, *entry = achievement_read_db_sub(id, count, filepath);
+
+				if (!entry) {
+					ShowWarning("achievement_read_db: Failed to parse achievement entry %d.\n", count);
+					continue;
+				}
+				if ((duplicate = achievement_search(entry->achievement_id)) != &achievement_dummy) {
+					if (!i) { // Normal file read-in
+						ShowWarning("achievement_read_db: Duplicate achievement %d.\n", entry->achievement_id);
+						achievement_db_free_sub(entry, false);
+						continue;
+					}
+					else // Import file read-in, free previous value and store new value
+						achievement_db_free_sub(duplicate, false);
+				}
+				yaml_destroy_wrapper(id);
+				idb_put(achievement_db, entry->achievement_id, entry);
+				count++;
+			}
+		}
+		yaml_destroy_wrapper(adb_sub);
+		yaml_iterator_destroy(it);
+
+		ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
+	}
+
+	return;
+}
+
+/**
+ * Recursive method to free an achievement condition
+ * @param condition: Condition to clear
+ */
+void achievement_script_free(struct av_condition *condition) 
+{
+	if (condition->left) {
+		achievement_script_free(condition->left);
+		condition->left = NULL;
+	}
+
+	if (condition->right) {
+		achievement_script_free(condition->right);
+		condition->right = NULL;
+	}
+
+	aFree(condition);
+}
+
+/**
+ * Clear achievement single entry
+ * @param achievement: Achievement to clear
+ * @param free: Will free achievement from memory
+ */
+void achievement_db_free_sub(struct achievement_db *achievement, bool free)
+{
+	if (achievement->targets) {
+		aFree(achievement->targets);
+		achievement->targets = NULL;
+		achievement->target_count = 0;
+	}
+	if (achievement->condition) {
+		achievement_script_free(achievement->condition);
+		achievement->condition = NULL;
+	}
+	if (achievement->dependents) {
+		aFree(achievement->dependents);
+		achievement->dependents = NULL;
+		achievement->dependent_count = 0;
+	}
+	if (achievement->rewards.script) {
+		script_free_code(achievement->rewards.script);
+		achievement->rewards.script = NULL;
+	}
+	if (free)
+		aFree(achievement);
+}
+
+/**
+ * Clears the achievement database for shutdown or reload.
+ */
+static int achievement_db_free(DBKey key, DBData *data, va_list ap)
+{
+	struct achievement_db *achievement = (struct achievement_db *)db_data2ptr(data);
+
+	if (!achievement)
+		return 0;
+
+	achievement_db_free_sub(achievement, true);
+	return 1;
+}
+
+static int achievementmobs_db_free(DBKey key, DBData *data, va_list ap)
+{
+	struct achievementmobs_db *achievement = (struct achievementmobs_db *)db_data2ptr(data);
+
+	if (!achievement)
+		return 0;
+
+	aFree(achievement);
+	return 1;
+}
+
+void achievement_db_reload(void)
+{
+	if (!battle_config.feature_achievement)
+		return;
+	achievementmobs_db->clear(achievementmobs_db, achievementmobs_db_free);
+	achievement_db->clear(achievement_db, achievement_db_free);
+	achievement_read_db();
+}
+
+void do_init_achievement(void)
+{
+	if (!battle_config.feature_achievement)
+		return;
+	memset(&achievement_dummy, 0, sizeof(achievement_dummy));
+	achievement_db = idb_alloc(DB_OPT_BASE);
+	achievementmobs_db = idb_alloc(DB_OPT_BASE);
+	achievement_read_db();
+}
+
+void do_final_achievement(void)
+{
+	if (!battle_config.feature_achievement)
+		return;
+	achievementmobs_db->destroy(achievementmobs_db, achievementmobs_db_free);
+	achievement_db->destroy(achievement_db, achievement_db_free);
+}

+ 135 - 0
src/map/achievement.h

@@ -0,0 +1,135 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef MAP_ACHIEVEMENTS_H
+#define MAP_ACHIEVEMENTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../common/mmo.h"
+#include "../common/db.h"
+
+enum e_achievement_group {
+	AG_NONE = 0,
+	AG_ADD_FRIEND,
+	AG_ADVENTURE,
+	AG_BABY,
+	AG_BATTLE,
+	AG_CHAT,
+	AG_CHAT_COUNT,
+	AG_CHAT_CREATE,
+	AG_CHAT_DYING,
+	AG_EAT,
+	AG_GET_ITEM,
+	AG_GET_ZENY,
+	AG_GOAL_ACHIEVE,
+	AG_GOAL_LEVEL,
+	AG_GOAL_STATUS,
+	AG_HEAR,
+	AG_JOB_CHANGE,
+	AG_MARRY,
+	AG_PARTY,
+	AG_REFINE_FAIL,
+	AG_REFINE_SUCCESS,
+	AG_SEE,
+	AG_SPEND_ZENY,
+	AG_TAMING,
+	AG_MAX
+};
+
+enum e_achievement_info {
+	ACHIEVEINFO_COUNT1 = 1,
+	ACHIEVEINFO_COUNT2,
+	ACHIEVEINFO_COUNT3,
+	ACHIEVEINFO_COUNT4,
+	ACHIEVEINFO_COUNT5,
+	ACHIEVEINFO_COUNT6,
+	ACHIEVEINFO_COUNT7,
+	ACHIEVEINFO_COUNT8,
+	ACHIEVEINFO_COUNT9,
+	ACHIEVEINFO_COUNT10,
+	ACHIEVEINFO_COMPLETE,
+	ACHIEVEINFO_COMPLETEDATE,
+	ACHIEVEINFO_GOTREWARD,
+	ACHIEVEINFO_LEVEL,
+	ACHIEVEINFO_SCORE,
+	ACHIEVEINFO_MAX,
+};
+
+struct achievement_mob {
+	int mod_id;
+};
+
+struct achievement_target {
+	int mob;
+	int count;
+};
+
+struct achievement_dependent {
+	int achievement_id;
+};
+
+struct av_condition {
+	int op;
+	struct av_condition *left;
+	struct av_condition *right;
+	long long value;
+};
+
+struct achievement_db {
+	int achievement_id;
+	char name[ACHIEVEMENT_NAME_LENGTH];
+	enum e_achievement_group group;
+	uint8 target_count;
+	struct achievement_target *targets;
+	uint8 dependent_count;
+	struct achievement_dependent *dependents;
+	struct av_condition *condition;
+	int16 mapindex;
+	struct ach_reward {
+		unsigned short nameid, amount;
+		struct script_code *script;
+		int title_id;
+	} rewards;
+	int score;
+	int has_dependent; // Used for quick updating of achievements that depend on others - this is their ID
+};
+
+struct map_session_data;
+struct block_list;
+struct config_setting_t;
+enum _sp;
+
+struct achievement_db achievement_dummy;	///< Dummy entry for invalid achievement lookups
+
+struct achievement_db *achievement_search(int achievement_id);
+bool achievement_mobexists(int mob_id);
+void achievement_get_reward(struct map_session_data *sd, int achievement_id, time_t rewarded);
+struct achievement *achievement_add(struct map_session_data *sd, int achievement_id);
+bool achievement_remove(struct map_session_data *sd, int achievement_id);
+bool achievement_update_achievement(struct map_session_data *sd, int achievement_id, bool complete);
+void achievement_check_reward(struct map_session_data *sd, int achievement_id);
+void achievement_free(struct map_session_data *sd);
+int achievement_check_progress(struct map_session_data *sd, int achievement_id, int type);
+int *achievement_level(struct map_session_data *sd, bool flag);
+void achievement_get_titles(uint32 char_id);
+void achievement_update_objective(struct map_session_data *sd, enum e_achievement_group group, uint8 arg_count, ...);
+void achievement_read_db(void);
+void achievement_db_reload(void);
+
+void do_init_achievement(void);
+void do_final_achievement(void);
+
+// Parser
+const char *av_parse_subexpr(const char *p,int limit, struct av_condition *parent);
+const char *av_parse_simpleexpr(const char *p, struct av_condition *parent);
+long long achievement_check_condition(struct av_condition *condition, struct map_session_data *sd, int *count);
+void achievement_script_free(struct av_condition *condition);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MAP_ACHIEVEMENTS_H */

+ 16 - 8
src/map/atcommand.c

@@ -34,6 +34,7 @@
 #include "mapreg.h"
 #include "quest.h"
 #include "pc.h"
+#include "achievement.h"
 
 #include <stdlib.h>
 #include <math.h>
@@ -185,12 +186,12 @@ ACMD_FUNC(send)
 		long num;
 		if(len)
 		{// show packet length
-			sprintf(atcmd_output, msg_txt(sd,904), type, packet_db[sd->packet_ver][type].len); // Packet 0x%x length: %d
+			sprintf(atcmd_output, msg_txt(sd,904), type, packet_db[type].len); // Packet 0x%x length: %d
 			clif_displaymessage(fd, atcmd_output);
 			return 0;
 		}
 
-		len=packet_db[sd->packet_ver][type].len;
+		len=packet_db[type].len;
 		off=2;
 		if(len == 0)
 		{// unknown packet - ERROR
@@ -341,7 +342,7 @@ ACMD_FUNC(send)
 			SKIP_VALUE(message);
 		}
 
-		if(packet_db[sd->packet_ver][type].len == -1)
+		if(packet_db[type].len == -1)
 		{// send dynamic packet
 			WFIFOW(fd,2)=TOW(off);
 			WFIFOSET(fd,off);
@@ -1422,6 +1423,8 @@ ACMD_FUNC(baselevelup)
 		status_calc_pc(sd, SCO_FORCE);
 		status_percent_heal(&sd->bl, 100, 100);
 		clif_misceffect(&sd->bl, 0);
+		achievement_update_objective(sd, AG_GOAL_LEVEL, 1, sd->status.base_level);
+		achievement_update_objective(sd, AG_GOAL_STATUS, 2, sd->status.base_level, sd->status.class_);
 		clif_displaymessage(fd, msg_txt(sd,21)); // Base level raised.
 	} else {
 		if (sd->status.base_level == 1) {
@@ -1483,6 +1486,7 @@ ACMD_FUNC(joblevelup)
 		sd->status.job_level += (unsigned int)level;
 		sd->status.skill_point += level;
 		clif_misceffect(&sd->bl, 1);
+		achievement_update_objective(sd, AG_GOAL_LEVEL, 1, sd->status.job_level);
 		clif_displaymessage(fd, msg_txt(sd,24)); // Job level raised.
 	} else {
 		if (sd->status.job_level == 1) {
@@ -1757,7 +1761,7 @@ ACMD_FUNC(bodystyle)
 		|| (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC || (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD
 		|| (sd->class_&MAPID_THIRDMASK) == MAPID_ARCH_BISHOP || (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER
 		|| (sd->class_&MAPID_THIRDMASK) == MAPID_WARLOCK || (sd->class_&MAPID_THIRDMASK) == MAPID_SHADOW_CHASER
-	        || (sd->class_&MAPID_THIRDMASK) == MAPID_MINSTRELWANDERER)) {
+	        || (sd->class_&MAPID_THIRDMASK) == MAPID_MINSTRELWANDERER || (sd->class_&MAPID_THIRDMASK) == MAPID_SORCERER)) {
 		clif_displaymessage(fd, msg_txt(sd,740));	// This job has no alternate body styles.
 		return -1;
 	}
@@ -1917,6 +1921,7 @@ ACMD_FUNC(go)
 		{ MAP_MALANGDO,    140, 114 }, // 33=Malangdo Island
 		{ MAP_MALAYA,      242, 211 }, // 34=Malaya Port
 		{ MAP_ECLAGE,      110,  39 }, // 35=Eclage
+		{ MAP_LASAGNA,     193, 182 }, // 36=Lasagna
 	};
 
 	nullpo_retr(-1, sd);
@@ -2036,6 +2041,8 @@ ACMD_FUNC(go)
 		town = 34;
 	} else if (strncmp(map_name, "eclage", 3) == 0) {
 		town = 35;
+	} else if (strncmp(map_name, "lasagna", 2) == 0) {
+		town = 36;
 	}
 
 	if (town >= 0 && town < ARRAYLENGTH(data))
@@ -2274,6 +2281,7 @@ ACMD_FUNC(refine)
 			clif_additem(sd, i, 1, 0);
 			pc_equipitem(sd, i, current_position);
 			clif_misceffect(&sd->bl, 3);
+			achievement_update_objective(sd, AG_REFINE_SUCCESS, 2, sd->inventory_data[i]->wlv, sd->inventory.u.items_inventory[i].refine);
 			count++;
 		}
 	}
@@ -3924,12 +3932,12 @@ ACMD_FUNC(reload) {
 	} else if (strstr(command, "questdb") || strncmp(message, "questdb", 3) == 0) {
 		do_reload_quest();
 		clif_displaymessage(fd, msg_txt(sd,1377)); // Quest database has been reloaded.
-	} else if (strstr(command, "packetdb") || strncmp(message, "packetdb", 4) == 0) {
-		packetdb_readdb(true);
-		clif_displaymessage(fd, msg_txt(sd,1477)); // Packet database has been reloaded.
 	} else if (strstr(command, "instancedb") || strncmp(message, "instancedb", 4) == 0) {
 		instance_reload();
 		clif_displaymessage(fd, msg_txt(sd,516)); // Instance database has been reloaded.
+	} else if (strstr(command, "achievementdb") || strncmp(message, "achievementdb", 4) == 0) {
+		achievement_db_reload();
+		clif_displaymessage(fd, msg_txt(sd,771)); // Achievement database has been reloaded.
 	}
 
 	return 0;
@@ -10082,8 +10090,8 @@ void atcommand_basecommands(void) {
 		ACMD_DEF2("reloadmotd", reload),
 		ACMD_DEF2("reloadquestdb", reload),
 		ACMD_DEF2("reloadmsgconf", reload),
-		ACMD_DEF2("reloadpacketdb", reload),
 		ACMD_DEF2("reloadinstancedb", reload),
+		ACMD_DEF2("reloadachievementdb",reload),
 		ACMD_DEF(partysharelvl),
 		ACMD_DEF(mapinfo),
 		ACMD_DEF(dye),

+ 8 - 2
src/map/battle.c

@@ -8194,8 +8194,6 @@ static const struct _battle_data {
 	{ "night_at_start",                     &battle_config.night_at_start,                  0,      0,      1,              },
 	{ "show_mob_info",                      &battle_config.show_mob_info,                   0,      0,      1|2|4,          },
 	{ "ban_hack_trade",                     &battle_config.ban_hack_trade,                  0,      0,      INT_MAX,        },
-	{ "packet_ver_flag",                    &battle_config.packet_ver_flag,                 0x7FFFFFFF,0,   INT_MAX,        },
-	{ "packet_ver_flag2",                   &battle_config.packet_ver_flag2,                0x7FFFFFFF,0,   INT_MAX,        },
 	{ "min_hair_style",                     &battle_config.min_hair_style,                  0,      0,      INT_MAX,        },
 	{ "max_hair_style",                     &battle_config.max_hair_style,                  23,     0,      INT_MAX,        },
 	{ "min_hair_color",                     &battle_config.min_hair_color,                  0,      0,      INT_MAX,        },
@@ -8429,6 +8427,7 @@ static const struct _battle_data {
 	{ "banana_bomb_duration",				&battle_config.banana_bomb_duration,			0,		0,		UINT16_MAX,		},
 	{ "guild_leaderchange_delay",			&battle_config.guild_leaderchange_delay,		1440,	0,		INT32_MAX,		},
 	{ "guild_leaderchange_woe",				&battle_config.guild_leaderchange_woe,			0,		0,		1,				},
+	{ "feature.achievement",                &battle_config.feature_achievement,             1,      0,      1,              },
 
 #include "../custom/battle_config_init.inc"
 };
@@ -8552,6 +8551,13 @@ void battle_adjust_conf()
 	}
 #endif
 
+#if PACKETVER < 20150513
+	if (battle_config.feature_achievement) {
+		ShowWarning("conf/battle/feature.conf achievement is enabled but it requires PACKETVER 2015-05-13 or newer, disabling...\n");
+		battle_config.feature_achievement = 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");

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio