summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in18
-rw-r--r--conf/Changelog.txt11
-rw-r--r--conf/battle/feature.conf28
-rw-r--r--conf/battle/gm.conf4
-rw-r--r--conf/battle/misc.conf7
-rw-r--r--conf/battle/party.conf4
-rw-r--r--conf/battle_athena.conf3
-rw-r--r--conf/char_athena.conf5
-rw-r--r--conf/log_athena.conf1
-rw-r--r--conf/mapflag/restricted.txt9
-rw-r--r--conf/msg_athena.conf9
-rwxr-xr-xconfigure339
-rw-r--r--configure.in107
-rw-r--r--db/Changelog.txt12
-rw-r--r--db/item_buyingstore.txt1013
-rw-r--r--db/item_db.txt29
-rw-r--r--db/packet_db.txt48
-rw-r--r--db/skill_db.txt3
-rw-r--r--db/skill_nocast_db.txt50
-rw-r--r--db/skill_require_db.txt2
-rw-r--r--db/skill_tree.txt11
-rw-r--r--doc/script_commands.txt41
-rw-r--r--npc/Changelog.txt30
-rw-r--r--npc/events/MemorialDay_2008.txt230
-rw-r--r--npc/events/StPatrick_2008.txt180
-rw-r--r--npc/events/christmas_2008.txt650
-rw-r--r--npc/events/gdevent_aru.txt18
-rw-r--r--npc/events/gdevent_sch.txt18
-rw-r--r--npc/events/halloween_2008.txt73
-rw-r--r--npc/events/valentinesday_2009.txt362
-rw-r--r--npc/instances/EndlessTower.txt10
-rw-r--r--npc/merchants/icecream.txt12
-rw-r--r--npc/merchants/socket_enchant.txt21
-rw-r--r--npc/merchants/socket_enchant2.txt12
-rw-r--r--npc/other/auction.txt13
-rw-r--r--npc/other/comodo_gambling.txt2
-rw-r--r--npc/other/mail.txt13
-rw-r--r--npc/other/mercenary_rent.txt8
-rw-r--r--npc/other/pvp.txt28
-rw-r--r--npc/quests/newgears/2006_headgear.txt6
-rw-r--r--npc/quests/quests_13_1.txt131
-rw-r--r--npc/quests/quests_lighthalzen.txt163
-rw-r--r--npc/quests/quests_moscovia.txt5
-rw-r--r--npc/quests/quests_veins.txt10
-rw-r--r--npc/quests/skills/rogue_skills.txt4
-rw-r--r--readme.html387
-rw-r--r--readme/changelog.html136
-rw-r--r--readme/commands.html32
-rw-r--r--readme/faq-content.html33
-rw-r--r--readme/faq.html182
-rw-r--r--readme/features.html159
-rw-r--r--readme/gmcommands.html139
-rw-r--r--readme/images/banner.gifbin27814 -> 0 bytes
-rw-r--r--readme/images/bg.gifbin1402 -> 3121 bytes
-rw-r--r--readme/images/btmborder.gifbin755 -> 0 bytes
-rw-r--r--readme/images/btmborderbg.gifbin567 -> 0 bytes
-rw-r--r--readme/images/chara.gifbin213372 -> 0 bytes
-rw-r--r--readme/images/clown.pngbin0 -> 590954 bytes
-rw-r--r--readme/images/leftbg.gifbin1260 -> 0 bytes
-rw-r--r--readme/images/leftborder.gifbin729 -> 0 bytes
-rw-r--r--readme/images/logo.gifbin26250 -> 0 bytes
-rw-r--r--readme/images/logobtm.gifbin912 -> 0 bytes
-rw-r--r--readme/images/rightbg.gifbin1253 -> 0 bytes
-rw-r--r--readme/images/rightborder.gifbin730 -> 0 bytes
-rw-r--r--readme/images/textbg.gifbin617 -> 0 bytes
-rw-r--r--readme/npcfeatures.html262
-rw-r--r--readme/readme.css227
-rw-r--r--readme/resources.html217
-rw-r--r--readme/scripting.html69
-rw-r--r--readme/setup.html206
-rw-r--r--readme/style.css80
-rw-r--r--sql-files/logs.sql8
-rw-r--r--sql-files/main.sql1
-rw-r--r--sql-files/upgrade_svn14700.sql1
-rw-r--r--sql-files/upgrade_svn14713_log.sql4
-rw-r--r--src/char/char.c321
-rw-r--r--src/char_sql/char.c266
-rw-r--r--src/common/mmo.h9
-rw-r--r--src/common/socket.c18
-rw-r--r--src/common/socket.h2
-rw-r--r--src/common/strlib.c3
-rw-r--r--src/common/strlib.h6
-rw-r--r--src/common/utils.c72
-rw-r--r--src/common/utils.h3
-rw-r--r--src/login/account_sql.c2
-rw-r--r--src/login/login.c7
-rw-r--r--src/map/Makefile.in6
-rw-r--r--src/map/atcommand.c22
-rw-r--r--src/map/battle.c6
-rw-r--r--src/map/battle.h6
-rw-r--r--src/map/buyingstore.c470
-rw-r--r--src/map/buyingstore.h33
-rw-r--r--src/map/chat.c7
-rw-r--r--src/map/clif.c947
-rw-r--r--src/map/clif.h62
-rw-r--r--src/map/itemdb.c27
-rw-r--r--src/map/itemdb.h1
-rw-r--r--src/map/log.c14
-rw-r--r--src/map/log.h7
-rw-r--r--src/map/mail.c2
-rw-r--r--src/map/map.c1
-rw-r--r--src/map/npc.c9
-rw-r--r--src/map/party.c4
-rw-r--r--src/map/pc.c13
-rw-r--r--src/map/pc.h19
-rw-r--r--src/map/script.c234
-rw-r--r--src/map/script.h3
-rw-r--r--src/map/searchstore.c405
-rw-r--r--src/map/searchstore.h57
-rw-r--r--src/map/skill.c18
-rw-r--r--src/map/status.c6
-rw-r--r--src/map/trade.c4
-rw-r--r--src/map/unit.c3
-rw-r--r--src/map/vending.c90
-rw-r--r--src/map/vending.h3
-rw-r--r--src/plugins/console.c6
-rwxr-xr-xtools/getlogincount.pl122
-rwxr-xr-xtools/item_db.pl1
-rwxr-xr-xtools/mapcheck.sh34
-rwxr-xr-xtools/mapchecker.sh56
-rwxr-xr-xtools/mob_db.pl2
-rw-r--r--vcproj-10/map-server_sql.vcxproj4
-rw-r--r--vcproj-10/map-server_txt.vcxproj4
-rw-r--r--vcproj-6/map-server_sql.dsp16
-rw-r--r--vcproj-6/map-server_txt.dsp16
-rw-r--r--vcproj-7.1/map-server_sql.vcproj12
-rw-r--r--vcproj-7.1/map-server_txt.vcproj12
-rw-r--r--vcproj-8/map-server_sql.vcproj16
-rw-r--r--vcproj-8/map-server_txt.vcproj16
-rw-r--r--vcproj-9/map-server_sql.vcproj16
-rw-r--r--vcproj-9/map-server_txt.vcproj16
131 files changed, 5826 insertions, 3607 deletions
diff --git a/Makefile.in b/Makefile.in
index 5b51affa4..667b79fbc 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -2,7 +2,7 @@
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
- ALL_DEPENDS=common common_sql login login_sql char char_sql map map_sql tools converters plugins import save
+ ALL_DEPENDS=common common_sql login login_sql char char_sql map map_sql tools converters import save
SQL_DEPENDS=common_sql login_sql char_sql map_sql import save
COMMON_SQL_DEPENDS=
LOGIN_SQL_DEPENDS=common_sql
@@ -10,7 +10,7 @@ ifeq ($(HAVE_MYSQL),yes)
MAP_SQL_DEPENDS=common_sql
CONVERTERS_DEPENDS=common_sql
else
- ALL_DEPENDS=common login char map tools plugins import save
+ ALL_DEPENDS=common login char map tools import save
SQL_DEPENDS=needs_mysql
COMMON_SQL_DEPENDS=needs_mysql
LOGIN_SQL_DEPENDS=needs_mysql
@@ -19,6 +19,14 @@ else
CONVERTERS_DEPENDS=needs_mysql
endif
+WITH_PLUGINS=@WITH_PLUGINS@
+ifeq ($(WITH_PLUGINS),yes)
+ ALL_DEPENDS+=plugins
+ PLUGIN_DEPENDS=common
+else
+ PLUGIN_DEPENDS=no_plugins
+endif
+
#####################################################################
.PHONY: txt sql conf \
common common_sql \
@@ -66,7 +74,7 @@ tools:
converters: $(CONVERTERS_DEPENDS)
@$(MAKE) -C src/txt-converter
-plugins addons: common
+plugins addons: $(PLUGIN_DEPENDS)
@$(MAKE) -C src/plugins
import:
@@ -129,6 +137,10 @@ needs_mysql:
@echo "MySQL not found or disabled by the configure script"
@exit 1
+no_plugins:
+ @echo "Plugins disabled by the configure script"
+ @exit 1
+
#####################################################################
# TODO
diff --git a/conf/Changelog.txt b/conf/Changelog.txt
index e726d3f61..3a1121934 100644
--- a/conf/Changelog.txt
+++ b/conf/Changelog.txt
@@ -1,5 +1,16 @@
Date Added
+2011/03/06
+ * Rev. 14732 Added search store info related settings. [Ai4rei]
+2011/02/23
+ * Rev. 14724 Made autotrade error message store type-neutral, as it is used for buying stores now as well. [Ai4rei]
+2011/02/19
+ * Rev. 14713 Added map-server feature settings file 'battle/feature.conf'. [Ai4rei]
+ - Added setting 'feature.buying_store' to enable/disable the buying store system.
+2011/02/15
+ * Rev. 14707 Added map-server battle setting 'gm_check_minlevel'. [Ai4rei]
+2011/02/06
+ * Rev. 14700 Added char-server setting 'char_del_delay'. [Ai4rei]
2011/01/13
* Rev. 14667 Removed ladmin settings (ladmin_athena.conf) and login-server settings for ladmin (login_athena.conf) (topic:262934). [Ai4rei]
2010/12/30
diff --git a/conf/battle/feature.conf b/conf/battle/feature.conf
new file mode 100644
index 000000000..ae1c00b33
--- /dev/null
+++ b/conf/battle/feature.conf
@@ -0,0 +1,28 @@
+// ______ __ __
+// /\ _ \/\ \__/\ \
+// __\ \ \L\ \ \ ,_\ \ \___ __ ___ __
+// /'__`\ \ __ \ \ \/\ \ _ `\ /'__`\/' _ `\ /'__`\
+///\ __/\ \ \/\ \ \ \_\ \ \ \ \/\ __//\ \/\ \/\ \L\.\_
+//\ \____\\ \_\ \_\ \__\\ \_\ \_\ \____\ \_\ \_\ \__/.\_\
+// \/____/ \/_/\/_/\/__/ \/_/\/_/\/____/\/_/\/_/\/__/\/_/
+// _ _ _ _ _ _ _ _ _ _ _ _ _
+// / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \
+//( e | n | g | l | i | s | h ) ( A | t | h | e | n | a )
+// \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
+//
+//--------------------------------------------------------------
+// eAthena Feature Configuration File
+//--------------------------------------------------------------
+// Note 1: Value is a config switch (on/off, yes/no or 1/0)
+// Note 2: Value is in percents (100 means 100%)
+// Note 3: Value is a bit field. If no description is given,
+// assume unit types (1: Pc, 2: Mob, 4: Pet, 8: Homun)
+//--------------------------------------------------------------
+
+// Buying store (Note 1)
+// Requires: 2010-04-27aRagexeRE or later
+feature.buying_store: on
+
+// Search stores (Note 1)
+// Requires: 2010-08-03aRagexeRE or later
+feature.search_stores: on
diff --git a/conf/battle/gm.conf b/conf/battle/gm.conf
index 5f15d2321..21b54f386 100644
--- a/conf/battle/gm.conf
+++ b/conf/battle/gm.conf
@@ -116,3 +116,7 @@ title_lvl5: 50
title_lvl6: 60
title_lvl7: 80
title_lvl8: 99
+
+// Minimum GM level required for client command /check (display character status) to work.
+// Default: 60
+gm_check_minlevel: 60
diff --git a/conf/battle/misc.conf b/conf/battle/misc.conf
index 8aa8b7c67..76d18ed0f 100644
--- a/conf/battle/misc.conf
+++ b/conf/battle/misc.conf
@@ -121,3 +121,10 @@ auction_feeperhour: 12000
// Auction maximum sell price
auction_maximumprice: 500000000
+
+// Minimum delay between each store search query in seconds.
+searchstore_querydelay: 10
+
+// Maximum amount of results a store search query may yield, before
+// it is canceled.
+searchstore_maxresults: 30
diff --git a/conf/battle/party.conf b/conf/battle/party.conf
index f0b2c8de2..42a9d2285 100644
--- a/conf/battle/party.conf
+++ b/conf/battle/party.conf
@@ -59,3 +59,7 @@ idle_no_share: no
// Give additional experience bonus per party-member involved on even-share parties?
// (eg: If set to 10, a even-share party of 5 people will receive +40% exp)
party_even_share_bonus: 0
+
+// Display party name regardless if player is in a guild.
+// Official servers do not display party name unless the user is in a guild. (Note 1)
+display_party_name: no
diff --git a/conf/battle_athena.conf b/conf/battle_athena.conf
index 7cf56ce1b..a867382a7 100644
--- a/conf/battle_athena.conf
+++ b/conf/battle_athena.conf
@@ -62,6 +62,9 @@ import: conf/battle/skill.conf
//Status change related settings
import: conf/battle/status.conf
+//Feature control (on/off) settings
+import: conf/battle/feature.conf
+
// Anything else that didn't fit anywhere else.
// Includes duel, day/night, mute/manner, log settings.
import: conf/battle/misc.conf
diff --git a/conf/char_athena.conf b/conf/char_athena.conf
index af0da9976..8e109f4da 100644
--- a/conf/char_athena.conf
+++ b/conf/char_athena.conf
@@ -166,6 +166,11 @@ chars_per_account: 0
// e.g. char_del_level: 80 (players can't delete characters with 80+ BaseLevel)
char_del_level: 0
+// Amount of time in seconds by which the character deletion is delayed.
+// Default: 86400 (24 hours)
+// NOTE: Requires client 2010-08-03aragexeRE or newer.
+char_del_delay: 86400
+
// What folder the DB files are in (item_db.txt, etc.)
db_path: db
diff --git a/conf/log_athena.conf b/conf/log_athena.conf
index 2f8effd18..0d5378a8f 100644
--- a/conf/log_athena.conf
+++ b/conf/log_athena.conf
@@ -16,6 +16,7 @@
// 2048 - (R) Log items placed/retrieved from storage.
// 4096 - (G) Log items placed/retrieved from guild storage.
// 8192 - (E) Log mail system transactions.
+// 16384 - (B) Log buying store transactions
// Example: Log trades+vending+script items+created items: 2+4+64+1024 = 1094
enable_logs: 1
diff --git a/conf/mapflag/restricted.txt b/conf/mapflag/restricted.txt
index 94920d422..6de962dff 100644
--- a/conf/mapflag/restricted.txt
+++ b/conf/mapflag/restricted.txt
@@ -5,6 +5,7 @@
//= eAthena Dev Team
//= 1.0 [Komurka]
//= 1.1 Added WoE:SE Map restrictions. [L0ne_W0lf]
+//= 1.2 Added Endless Tower Restrictions. (bugreport:4707) [L0ne_W0lf]
//===== Current Version: =====================================
//Aldebaran Turbo Track
@@ -45,3 +46,11 @@ arug_cas05 mapflag restricted 4
//Sealed Shrine ==================
1@cata mapflag restricted 5
2@cata mapflag restricted 5
+
+//Endless Tower ==================
+1@tower mapflag restricted 6
+2@tower mapflag restricted 6
+3@tower mapflag restricted 6
+4@tower mapflag restricted 6
+5@tower mapflag restricted 6
+6@tower mapflag restricted 6
diff --git a/conf/msg_athena.conf b/conf/msg_athena.conf
index 1c9b994c0..1d88c076a 100644
--- a/conf/msg_athena.conf
+++ b/conf/msg_athena.conf
@@ -423,12 +423,7 @@
502: Day Mode is activated
503: Night Mode is activated
-//Supernovice's Guardian Angel
-//actually.. new client msgtxt file contains these 3 lines... [Lupus]
-//----------------------------
-504: Guardian Angel, can you hear my voice? ^^;
-505: My name is %s, and I'm a Super Novice~
-506: Please help me~ T.T
+// 504~506 are not used (previously super novice's guardian angel prayer)
// Trade Spoof Messages
507: This player has been banned for %d minute(s).
@@ -455,7 +450,7 @@
//542: %.0s%.0sSomeone stole %s
// 543~548 are not used (previously @away messages)
// @Autotrade
-549: You should be vending to use @autotrade.
+549: You should have a shop open to use @autotrade.
//550 -> 650: Job Names
550: Novice
diff --git a/configure b/configure
index 3a5c7274c..0412b30eb 100755
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
#! /bin/sh
-# From configure.in Revision: 13486 .
+# From configure.in Revision: 14708 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59.
#
@@ -311,7 +311,7 @@ ac_includes_default="\
# include <unistd.h>
#endif"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS SET_MAKE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP MYSQL_CONFIG_HOME HAVE_MYSQL MYSQL_VERSION MYSQL_CFLAGS MYSQL_LIBS HAVE_PCRE PCRE_LIBS PCRE_CFLAGS DLLEXT LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS SET_MAKE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP WITH_PLUGINS EGREP MYSQL_CONFIG_HOME HAVE_MYSQL MYSQL_VERSION MYSQL_CFLAGS MYSQL_LIBS HAVE_PCRE PCRE_LIBS PCRE_CFLAGS DLLEXT LIBOBJS LTLIBOBJS'
ac_subst_files=''
# Initialize some variables set by options.
@@ -1333,7 +1333,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_config_files="$ac_config_files Makefile src/common/Makefile"
- ac_config_files="$ac_config_files src/char/Makefile src/login/Makefile"
+ ac_config_files="$ac_config_files src/char/Makefile src/login/Makefile"
ac_config_files="$ac_config_files src/char_sql/Makefile src/txt-converter/Makefile"
@@ -3257,6 +3257,240 @@ fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: checking whether $CC supports -fPIC" >&5
+echo $ECHO_N "checking whether $CC supports -fPIC... $ECHO_C" >&6
+OLD_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -fPIC"
+cat >conftest.$ac_ext <<_ACEOF
+int foo;
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ compiler_supports_pic="yes"
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ compiler_supports_pic="no"
+
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS="$OLD_CFLAGS"
+
+
+#
+# -shared needs position independent code; some platforms emit it
+# always, others need -fPIC
+#
+echo "$as_me:$LINENO: checking whether $CC needs -fPIC for shared objects" >&5
+echo $ECHO_N "checking whether $CC needs -fPIC for shared objects... $ECHO_C" >&6
+OLD_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -shared"
+WITH_PLUGINS="yes"
+cat >conftest.$ac_ext <<_ACEOF
+
+ int foo(void)
+ {
+ return 0;
+ }
+
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ CFLAGS="$OLD_CFLAGS"
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+ if test "$compiler_supports_pic" = "yes" ; then
+ # Verify if -shared really fails due to lack of -fPIC or something else
+ CFLAGS="$CFLAGS -fPIC"
+ cat >conftest.$ac_ext <<_ACEOF
+
+ int foo(void)
+ {
+ return 0;
+ }
+
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ CFLAGS="$OLD_CFLAGS -fPIC"
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+ echo "$as_me:$LINENO: result: no, but fails for another reason" >&5
+echo "${ECHO_T}no, but fails for another reason" >&6
+ { { echo "$as_me:$LINENO: error: compiler is unable to compile shared objects for an unhandled reason, please report this with attached config.log... stopping" >&5
+echo "$as_me: error: compiler is unable to compile shared objects for an unhandled reason, please report this with attached config.log... stopping" >&2;}
+ { (exit 1); exit 1; }; }
+
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ else
+ # Disable compilation of plugins (optional), so 'make all' does not fail
+ echo "$as_me:$LINENO: result: yes, but unsupported" >&5
+echo "${ECHO_T}yes, but unsupported" >&6
+ { echo "$as_me:$LINENO: compiler is unable to generate position independent code, disabled plugins (optional)" >&5
+echo "$as_me: compiler is unable to generate position independent code, disabled plugins (optional)" >&6;}
+ WITH_PLUGINS="no"
+ fi
+
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+
+
+#
+# DB_MANUAL_CAST_TO_UNION
+#
+echo "$as_me:$LINENO: checking whether $CC is able to typecast to union" >&5
+echo $ECHO_N "checking whether $CC is able to typecast to union... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+
+ typedef union Foonion
+ {
+ int i;
+ unsigned int ui;
+ const char* s;
+ }
+ Foonion;
+
+ int bar(Foonion onion)
+ {
+ return onion.i;
+ }
+
+ int foo(void)
+ {
+ int i = 0;
+
+ return bar(((Foonion)(int)i));
+ }
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ CFLAGS="$CFLAGS -DDB_MANUAL_CAST_TO_UNION"
+
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
###############################################################################
# Check for libraries and header files.
@@ -3362,6 +3596,104 @@ fi
+#
+# strnlen - string length with upper scan bound
+#
+echo "$as_me:$LINENO: checking for strnlen" >&5
+echo $ECHO_N "checking for strnlen... $ECHO_C" >&6
+if test "${ac_cv_func_strnlen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define strnlen to an innocuous variant, in case <limits.h> declares strnlen.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define strnlen innocuous_strnlen
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char strnlen (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef strnlen
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strnlen ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_strnlen) || defined (__stub___strnlen)
+choke me
+#else
+char (*f) () = strnlen;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != strnlen;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_strnlen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_strnlen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_strnlen" >&5
+echo "${ECHO_T}$ac_cv_func_strnlen" >&6
+if test $ac_cv_func_strnlen = yes; then
+ CFLAGS="$CFLAGS -DHAVE_STRNLEN"
+fi
+
+
#
# Memory manager
@@ -5725,6 +6057,7 @@ s,@ac_ct_CC@,$ac_ct_CC,;t t
s,@EXEEXT@,$EXEEXT,;t t
s,@OBJEXT@,$OBJEXT,;t t
s,@CPP@,$CPP,;t t
+s,@WITH_PLUGINS@,$WITH_PLUGINS,;t t
s,@EGREP@,$EGREP,;t t
s,@MYSQL_CONFIG_HOME@,$MYSQL_CONFIG_HOME,;t t
s,@HAVE_MYSQL@,$HAVE_MYSQL,;t t
diff --git a/configure.in b/configure.in
index bf3c97374..afc35ee3a 100644
--- a/configure.in
+++ b/configure.in
@@ -339,6 +339,108 @@ AC_COMPILE_IFELSE(
)
+AC_MSG_CHECKING([whether $CC supports -fPIC])
+OLD_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -fPIC"
+AC_COMPILE_IFELSE(
+ [int foo;],
+ [
+ AC_MSG_RESULT([yes])
+ compiler_supports_pic="yes"
+ ],
+ [
+ AC_MSG_RESULT([no])
+ compiler_supports_pic="no"
+ ]
+)
+CFLAGS="$OLD_CFLAGS"
+
+
+#
+# -shared needs position independent code; some platforms emit it
+# always, others need -fPIC
+#
+AC_MSG_CHECKING([whether $CC needs -fPIC for shared objects])
+OLD_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -shared"
+WITH_PLUGINS="yes"
+AC_LINK_IFELSE(
+ [
+ int foo(void)
+ {
+ return 0;
+ }
+ ],
+ [
+ AC_MSG_RESULT([no])
+ CFLAGS="$OLD_CFLAGS"
+ ],
+ [
+ if test "$compiler_supports_pic" = "yes" ; then
+ # Verify if -shared really fails due to lack of -fPIC or something else
+ CFLAGS="$CFLAGS -fPIC"
+ AC_LINK_IFELSE(
+ [
+ int foo(void)
+ {
+ return 0;
+ }
+ ],
+ [
+ AC_MSG_RESULT([yes])
+ CFLAGS="$OLD_CFLAGS -fPIC"
+ ],
+ [
+ AC_MSG_RESULT([no, but fails for another reason])
+ AC_MSG_ERROR([compiler is unable to compile shared objects for an unhandled reason, please report this with attached config.log... stopping])
+ ]
+ )
+ else
+ # Disable compilation of plugins (optional), so 'make all' does not fail
+ AC_MSG_RESULT([yes, but unsupported])
+ AC_MSG_NOTICE([compiler is unable to generate position independent code, disabled plugins (optional)])
+ WITH_PLUGINS="no"
+ fi
+ ]
+)
+AC_SUBST([WITH_PLUGINS])
+
+
+#
+# DB_MANUAL_CAST_TO_UNION
+#
+AC_MSG_CHECKING([whether $CC is able to typecast to union])
+AC_COMPILE_IFELSE(
+ [
+ typedef union Foonion
+ {
+ int i;
+ unsigned int ui;
+ const char* s;
+ }
+ Foonion;
+
+ int bar(Foonion onion)
+ {
+ return onion.i;
+ }
+
+ int foo(void)
+ {
+ int i = 0;
+
+ return bar(((Foonion)(int)i));
+ }
+ ],
+ [
+ AC_MSG_RESULT([yes])
+ ],
+ [
+ AC_MSG_RESULT([no])
+ CFLAGS="$CFLAGS -DDB_MANUAL_CAST_TO_UNION"
+ ]
+)
+
###############################################################################
# Check for libraries and header files.
@@ -351,6 +453,11 @@ AC_COMPILE_IFELSE(
AC_CHECK_FUNC([setrlimit],[CFLAGS="$CFLAGS -DHAVE_SETRLIMIT"])
+#
+# strnlen - string length with upper scan bound
+#
+AC_CHECK_FUNC([strnlen],[CFLAGS="$CFLAGS -DHAVE_STRNLEN"])
+
#
# Memory manager
diff --git a/db/Changelog.txt b/db/Changelog.txt
index 45477f3cf..7730b3888 100644
--- a/db/Changelog.txt
+++ b/db/Changelog.txt
@@ -9,6 +9,18 @@
13005 Angelic Wing Dagger: NEED INFO.
=======================
+2011/03/06
+ * Rev. 14732 Added Universal Catalog Silver, Gold and Bronze and their respective boxes. [Ai4rei]
+ - Updated packet info related to search store info.
+2011/02/19
+ * Rev. 14713 Database updates required by buying store system implementation. [Ai4rei]
+ - Added database of items, that can be sold to a buying store (item_buyingstore.txt).
+ - Added items Buy_Stall_Permit (6377) and Shabby_Purchase_Street_Stall_License (12548).
+ - Updated packet database with buying store related packets.
+ - Added skill 'Open Buying Store' (ALL_BUYING_STORE).
+2011/02/06
+ * Rev. 14697 Added the missing restricted skills to zone 6 for Endless Tower. (bugreport:4707) [L0ne_W0lf]
+ * Adjusted the rates for item using bAddEffOnSkill bonus.
2011/01/23
* Rev. 14679 Updated Aegis NPC ID constants from current npcidentity.lub (bugreport:4706). [Ai4rei]
- Fixes some incorrect NPC ID constants (since r12780).
diff --git a/db/item_buyingstore.txt b/db/item_buyingstore.txt
new file mode 100644
index 000000000..ec336c2a1
--- /dev/null
+++ b/db/item_buyingstore.txt
@@ -0,0 +1,1013 @@
+// Buying Store Item List
+// List of items, that can be sold to buying stores.
+// Format: <item id>
+// Example:
+// 512 // Apple
+// Note:
+// Items are in same order as data\buyingstoreitemlist.txt, which
+// must be edited as well for the client to accept added items.
+
+// items from 2010-03-12 update
+601 // Wing_Of_Fly
+602 // Wing_Of_Butterfly
+603 // Old_Blue_Box
+604 // Branch_Of_Dead_Tree
+605 // Anodyne
+606 // Aloebera
+607 // Yggdrasilberry
+608 // Seed_Of_Yggdrasil
+609 // Amulet
+610 // Leaf_Of_Yggdrasil
+611 // Spectacles
+612 // Portable_Furnace
+613 // Iron_Hammer
+614 // Golden_Hammer
+615 // Oridecon_Hammer
+616 // Old_Card_Album
+617 // Old_Violet_Box
+618 // Worn_Out_Scroll
+619 // Unripe_Apple
+620 // Orange_Juice
+621 // Bitter_Herb
+622 // Rainbow_Carrot
+623 // Earthworm_The_Dude
+624 // Rotten_Fish
+625 // Lusty_Iron
+626 // Monster_Juice
+627 // Sweet_Milk
+628 // Well_Dried_Bone
+629 // Singing_Flower
+630 // Dew_Laden_Moss
+631 // Deadly_Noxious_Herb
+632 // Fatty_Chubby_Earthworm
+633 // Baked_Yam
+634 // Tropical_Banana
+635 // Horror_Of_Tribe
+636 // No_Recipient
+637 // Old_Broom
+638 // Silver_Knife_Of_Chaste
+639 // Armlet_Of_Obedience
+640 // Shining_Stone
+641 // Contracts_In_Shadow
+642 // Book_Of_Devil
+643 // Pet_Incubator
+644 // Gift_Box
+645 // Center_Potion
+656 // Awakening_Potion
+657 // Berserk_Potion
+658 // Union_Of_Tribe
+659 // Heart_Of_Her
+660 // Prohibition_Red_Candle
+661 // Sway_Apron
+662 // Inspector_Certificate
+663 // Korea_Rice_Cake
+664 // Gift_Box_1
+665 // Gift_Box_2
+666 // Gift_Box_3
+667 // Gift_Box_4
+668 // Handsei
+669 // Rice_Cake_Soup
+678 // Poison_Bottle
+679 // Gold_Pill
+681 // Memory_Of_Wedding
+682 // Realgar_Wine
+683 // Exorcize_Herb
+684 // Durian
+686 // Earth_Scroll_1_3
+687 // Earth_Scroll_1_5
+688 // Cold_Scroll_1_3
+689 // Cold_Scroll_1_5
+690 // Fire_Scroll_1_3
+691 // Fire_Scroll_1_5
+692 // Wind_Scroll_1_3
+693 // Wind_Scroll_1_5
+694 // Ghost_Scroll_1_3
+695 // Ghost_Scroll_1_5
+696 // Fire_Scroll_2_1
+697 // Fire_Scroll_2_5
+698 // Fire_Scroll_3_1
+699 // Fire_Scroll_3_5
+700 // Cold_Scroll_2_1
+12000 // Cold_Scroll_2_5
+12001 // Holy_Scroll_1_3
+12002 // Holy_Scroll_1_5
+12003 // Holy_Scroll_2_1
+12004 // Arrow_Container
+12005 // Iron_Arrow_Container
+12006 // Steel_Arrow_Container
+12007 // Ori_Arrow_Container
+12008 // Fire_Arrow_Container
+12009 // Silver_Arrow_Container
+12010 // Wind_Arrow_Container
+12011 // Stone_Arrow_Container
+12012 // Crystal_Arrow_Container
+12013 // Shadow_Arrow_Container
+12014 // Imma_Arrow_Container
+12015 // Rusty_Arrow_Container
+12016 // Speed_Up_Potion
+12017 // Slow_Down_Potion
+12018 // Fire_Cracker
+12020 // Water_Of_Darkness
+12027 // Giggling_Box
+12028 // Box_Of_Thunder
+12029 // Gloomy_Box
+12030 // Box_Of_Grudge
+12031 // Sleepy_Box
+12032 // Box_Of_Storm
+12033 // Box_Of_Sunlight
+12034 // Painting_Box
+12040 // Stone_Of_Intelligence_
+12041 // Str_Dish01
+12042 // Str_Dish02
+12043 // Str_Dish03
+12044 // Str_Dish04
+12045 // Str_Dish05
+12046 // Int_Dish01
+12047 // Int_Dish02
+12048 // Int_Dish03
+12049 // Int_Dish04
+12050 // Int_Dish05
+12051 // Vit_Dish01
+12052 // Vit_Dish02
+12053 // Vit_Dish03
+12054 // Vit_Dish04
+12055 // Vit_Dish05
+12056 // Agi_Dish01
+12057 // Agi_Dish02
+12058 // Agi_Dish03
+12059 // Agi_Dish04
+12060 // Agi_Dish05
+12061 // Dex_Dish01
+12062 // Dex_Dish02
+12063 // Dex_Dish03
+12064 // Dex_Dish04
+12065 // Dex_Dish05
+12066 // Luk_Dish01
+12067 // Luk_Dish02
+12068 // Luk_Dish03
+12069 // Luk_Dish04
+12070 // Luk_Dish05
+12071 // Str_Dish06
+12072 // Str_Dish07
+12073 // Str_Dish08
+12074 // Str_Dish09
+12075 // Str_Dish10
+12076 // Int_Dish06
+12077 // Int_Dish07
+12078 // Int_Dish08
+12079 // Int_Dish09
+12080 // Int_Dish10
+12081 // Vit_Dish06
+12082 // Vit_Dish07
+12083 // Vit_Dish08
+12084 // Vit_Dish09
+12085 // Vit_Dish10
+12086 // Agi_Dish06
+12087 // Agi_Dish07
+12088 // Agi_Dish08
+12089 // Agi_Dish09
+12090 // Agi_Dish10
+12091 // Dex_Dish06
+12092 // Dex_Dish07
+12093 // Dex_Dish08
+12094 // Dex_Dish09
+12095 // Dex_Dish10
+12096 // Luk_Dish06
+12097 // Luk_Dish07
+12098 // Luk_Dish08
+12099 // Luk_Dish09
+12100 // Luk_Dish10
+12101 // Citron
+12102 // Meat_Skewer
+12103 // Bloody_Dead_Branch
+12104 // Random_Quiver
+12105 // Set_Of_Taiming_Item
+12106 // Accessory_Box
+12107 // Wrapped_Mask
+12108 // Bundle_Of_Magic_Scroll
+12109 // Poring_Box
+12110 // First_Aid_Kit
+12111 // Food_Package
+12112 // Tropical_Sograt
+12113 // Vermilion_The_Beach
+12114 // Elemental_Fire
+12115 // Elemental_Water
+12116 // Elemental_Earth
+12117 // Elemental_Wind
+12118 // Resist_Fire
+12119 // Resist_Water
+12120 // Resist_Earth
+12121 // Resist_Wind
+12122 // Sesame_Pastry
+12123 // Honey_Pastry
+12124 // Rainbow_Cake
+12125 // Outdoor_Cooking_Kits
+12126 // Indoor_Cooking_Kits
+12127 // High_end_Cooking_Kits
+12128 // Imperial_Cooking_Kits
+12129 // Fantastic_Cooking_Kits
+12130 // Cookie_Bag
+12132 // Red_Bag
+12144 // Sphere_Case_Wind
+12145 // Sphere_Case_Darkness
+12146 // Sphere_Case_Poison
+12147 // Sphere_Case_Water
+12148 // Sphere_Case_Fire
+12149 // Bullet_Case
+12150 // Bullet_Case_Blood
+12151 // Bullet_Case_Silver
+12183 // Holy_Arrow_Quiver
+12184 // Mercenary_Red_Potion
+12185 // Mercenary_Blue_Potion
+12194 // Hometown_Gift
+12195 // Plain_Rice_Cake
+12196 // Hearty_Rice_Cake
+12197 // Salty_Rice_Cake
+12198 // Lucky_Rice_Cake
+12241 // M_Center_Potion
+12242 // M_Awakening_Potion
+12243 // M_Berserk_Potion
+12246 // Magic_Card_Album
+12260 // Cool_Summer_Outfit
+12290 // Mysterious_Can
+12291 // Mysterious_PET_Bottle
+12292 // Unripe_Fruit
+12293 // Dried_Yggdrasilberry
+12341 // Special_Alloy_Trap_Box
+12346 // Unripe_Acorn
+12347 // Acorn_Jelly
+12353 // Tiny_Waterbottle
+12358 // Fan_Of_Wind
+12359 // Very_Soft_Plant
+12360 // Very_Red_Juice
+12362 // Kuloren
+12364 // Staff_Of_Leader
+12365 // Charming_Lotus
+12366 // Gril_Doll
+12367 // Luxury_Whisky_Bottle
+12368 // Splendid_Mirror
+12369 // Coconut
+12371 // Magical_Lithography
+12372 // Hell_Contract
+12373 // Boy's_Naivety
+12374 // Flaming_Ice
+12376 // Mysterious_Can2
+12377 // Mysterious_PET_Bottle2
+12379 // Pope's_Cookie
+12383 // Vulcan_Bullet_Magazine
+12392 // RepairA
+12393 // RepairB
+12394 // RepairC
+12395 // Tantanmen
+//12414
+12717 // Poison_Paralysis
+12718 // Poison_Leech
+12719 // Poison_Oblivion
+12720 // Poison_Contamination
+12721 // Poison_Numb
+12722 // Poison_Fever
+12723 // Poison_Laughing
+12724 // Poison_Fatigue
+12734 // Runstone_Quality
+12735 // Runstone_Ancient
+12736 // Runstone_Mystic
+12737 // Runstone_Ordinary
+12738 // Runstone_Rare
+506 // Green_Potion
+507 // Red_Herb
+508 // Yellow_Herb
+509 // White_Herb
+510 // Blue_Herb
+511 // Green_Herb
+512 // Apple
+513 // Banana
+514 // Grape
+515 // Carrot
+516 // Sweet_Potato
+517 // Meat
+518 // Honey
+519 // Milk
+520 // Leaflet_Of_Hinal
+521 // Leaflet_Of_Aloe
+522 // Fruit_Of_Mastela
+523 // Holy_Water
+525 // Panacea
+526 // Royal_Jelly
+528 // Monster's_Feed
+529 // Candy
+530 // Candy_Striper
+531 // Apple_Juice
+532 // Banana_Juice
+533 // Grape_Juice
+534 // Carrot_Juice
+535 // Pumpkin
+536 // Ice_Cream
+537 // Pet_Food
+538 // Well_Baked_Cookie
+539 // Piece_Of_Cake
+544 // Fish_Slice
+548 // Cheese
+549 // Nice_Sweet_Potato
+550 // Popped_Rice
+551 // Shusi
+553 // Bun
+564 // Rice_Ball
+566 // Tomyumkung
+567 // Prawn
+568 // Lemon
+569 // Novice_Potion
+570 // Lucky_Candy
+571 // Lucky_Candy_Cane
+572 // Lucky_Cookie
+574 // Egg
+576 // Prickly_Fruit
+577 // Grain
+578 // Strawberry
+579 // Delicious_Fish
+580 // Bread
+581 // Mushroom
+582 // Orange
+584 // Fish_Ball_Soup
+587 // Prickly_Fruit_
+591 // Caviar_Pancake
+592 // Jam_Pancake
+593 // Honey_Pancake
+594 // Sour_Cream_Pancake
+595 // Mushroom_Pancake
+//11513
+11515 // Coconut
+11516 // Acai_Fruit
+//11517
+701 // Ora_Ora
+702 // Animal_Blood
+703 // Hinalle
+704 // Aloe
+705 // Clover
+706 // Four_Leaf_Clover
+707 // Singing_Plant
+708 // Ment
+709 // Izidor
+710 // Illusion_Flower
+711 // Shoot
+712 // Flower
+713 // Empty_Bottle
+715 // Yellow_Gemstone
+716 // Red_Gemstone
+717 // Blue_Gemstone
+718 // Dark_Red_Jewel
+719 // Violet_Jewel
+720 // Skyblue_Jewel
+721 // Azure_Jewel
+722 // Scarlet_Jewel
+723 // Cardinal_Jewel
+724 // Cardinal_Jewel_
+725 // Red_Jewel
+726 // Blue_Jewel
+727 // White_Jewel
+728 // Golden_Jewel
+729 // Bluish_Green_Jewel
+730 // Crystal_Jewel
+731 // Crystal_Jewel_
+732 // Crystal_Jewel__
+733 // Crystal_Jewel___
+734 // Red_Frame
+735 // Blue_Porcelain
+736 // White_Platter
+737 // Black_Ladle
+738 // Pencil_Case
+739 // Rouge
+740 // Stuffed_Doll
+741 // Poring_Doll
+742 // Chonchon_Doll
+743 // Spore_Doll
+744 // Bunch_Of_Flowers
+745 // Wedding_Bouquet
+746 // Glass_Bead
+747 // Crystal_Mirror
+748 // Witherless_Rose
+749 // Frozen_Rose
+750 // Baphomet_Doll
+751 // Osiris_Doll
+752 // Grasshopper_Doll
+753 // Monkey_Doll
+754 // Raccoondog_Doll
+756 // Oridecon_Stone
+757 // Elunium_Stone
+901 // Danggie
+902 // Tree_Root
+903 // Reptile_Tongue
+904 // Scorpion's_Tail
+905 // Stem
+906 // Pointed_Scale
+907 // Resin
+908 // Spawn
+909 // Jellopy
+910 // Garlet
+911 // Scell
+912 // Zargon
+913 // Tooth_Of_Bat
+914 // Fluff
+915 // Chrysalis
+916 // Feather_Of_Birds
+917 // Talon
+918 // Sticky_Webfoot
+919 // Animal's_Skin
+920 // Claw_Of_Wolves
+921 // Mushroom_Spore
+922 // Orcish_Cuspid
+923 // Evil_Horn
+924 // Powder_Of_Butterfly
+925 // Bill_Of_Birds
+926 // Scale_Of_Snakes
+928 // Insect_Feeler
+929 // Immortal_Heart
+930 // Rotten_Bandage
+931 // Orcish_Voucher
+932 // Skel_Bone
+934 // Mementos
+935 // Shell
+936 // Scales_Shell
+937 // Posionous_Canine
+938 // Sticky_Mucus
+939 // Bee_Sting
+940 // Grasshopper's_Leg
+941 // Nose_Ring
+942 // Yoyo_Tail
+943 // Solid_Shell
+944 // Horseshoe
+945 // Raccoon_Leaf
+946 // Snail's_Shell
+947 // Horn
+948 // Bear's_Foot
+949 // Feather
+950 // Heart_Of_Mermaid
+951 // Fin
+952 // Cactus_Needle
+953 // Stone_Heart
+954 // Shining_Scales
+955 // Worm_Peelings
+956 // Gill
+957 // Decayed_Nail
+958 // Horrendous_Mouth
+959 // Rotten_Scale
+960 // Nipper
+961 // Conch
+962 // Tentacle
+963 // Sharp_Scale
+964 // Crap_Shell
+965 // Clam_Shell
+966 // Flesh_Of_Clam
+967 // Turtle_Shell
+968 // Voucher_Of_Orcish_Hero
+969 // Gold
+971 // Detrimindexta
+972 // Karvodailnirol
+973 // Counteragent
+974 // Mixture
+975 // Scarlet_Dyestuffs
+976 // Lemon_Dyestuffs
+978 // Cobaltblue_Dyestuffs
+979 // Darkgreen_Dyestuffs
+980 // Orange_Dyestuffs
+981 // Violet_Dyestuffs
+982 // White_Dyestuffs
+983 // Black_Dyestuffs
+984 // Oridecon
+985 // Elunium
+986 // Anvil
+987 // Oridecon_Anvil
+988 // Golden_Anvil
+989 // Emperium_Anvil
+990 // Boody_Red
+991 // Crystal_Blue
+992 // Wind_Of_Verdure
+993 // Yellow_Live
+994 // Flame_Heart
+995 // Mistic_Frozen
+996 // Rough_Wind
+997 // Great_Nature
+998 // Iron
+999 // Steel
+1000 // Star_Crumb
+1001 // Sparkling_Dust
+1002 // Iron_Ore
+1003 // Coal
+1004 // Patriotism_Marks
+1005 // Hammer_Of_Blacksmith
+1006 // Old_Magic_Book
+1007 // Penetration
+1008 // Frozen_Heart
+1009 // Sacred_Marks
+1010 // Phracon
+1011 // Emveretarcon
+1012 // Lizard_Scruff
+1013 // Colorful_Shell
+1014 // Jaws_Of_Ant
+1015 // Thin_N'_Long_Tongue
+1016 // Rat_Tail
+1017 // Moustache_Of_Mole
+1018 // Nail_Of_Mole
+1019 // Wooden_Block
+1020 // Long_Hair
+1021 // Dokkaebi_Horn
+1022 // Fox_Tail
+1023 // Fish_Tail
+1024 // Chinese_Ink
+1025 // Spiderweb
+1026 // Acorn
+1027 // Porcupine_Spike
+1028 // Wild_Boar's_Mane
+1029 // Tiger's_Skin
+1030 // Tiger_Footskin
+1031 // Limb_Of_Mantis
+1032 // Blossom_Of_Maneater
+1033 // Root_Of_Maneater
+1034 // Cobold_Hair
+1035 // Dragon_Canine
+1036 // Dragon_Scale
+1037 // Dragon_Train
+1038 // Petite_DiablOfs_Horn
+1039 // Petite_DiablOfs_Wing
+1040 // Elder_Pixie's_Beard
+1041 // Lantern
+1042 // Short_Leg
+1043 // Nail_Of_Orc
+1044 // Tooth_Of_
+1045 // Sacred_Masque
+1046 // Tweezer
+1047 // Head_Of_Medusa
+1048 // Slender_Snake
+1049 // Skirt_Of_Virgin
+1050 // Tendon
+1051 // Detonator
+1052 // Single_Cell
+1053 // Tooth_Of_Ancient_Fish
+1054 // Lip_Of_Ancient_Fish
+1055 // Earthworm_Peeling
+1056 // Grit
+1057 // Moth_Dust
+1058 // Wing_Of_Moth
+1059 // Transparent_Cloth
+1060 // Golden_Hair
+1061 // Starsand_Of_Witch
+1062 // Pumpkin_Head
+1063 // Sharpened_Cuspid
+1064 // Reins
+1065 // Booby_Trap
+1066 // Tree_Of_Archer_1
+1067 // Tree_Of_Archer_2
+1068 // Tree_Of_Archer_3
+1088 // Morocc_Potion
+1089 // Payon_Potion
+1092 // Empty_Cylinder
+1093 // Empty_Potion
+1094 // Short_Daenggie
+1095 // Needle_Of_Alarm
+1096 // Round_Shell
+1097 // Worn_Out_Page
+1098 // Manacles
+1099 // Worn_Out_Prison_Uniform
+6001 // Essence_Of_Fire
+6002 // Token_Of_Apostle
+6003 // Soul_Pendant
+6004 // Bapho_Doll
+6008 // Wood
+6010 // Pickaxe
+6020 // Fur
+6021 // Peaked_Hat
+6022 // Hard_Skin
+6023 // Mystic_Horn
+6032 // Horn_Of_Hilsrion
+6033 // Horn_Of_Tendrilion
+6073 // Dragon's_Mane
+6075 // Crystalized_Teardrop
+6086 // Withered_Flower
+6087 // Crystal_Of_Soul_01
+6088 // Crystal_Of_Soul_02
+6089 // Piece_Of_Darkness
+6090 // Purified_Bradium
+6091 // Dark_Red_Scale
+6095 // Flavored_Alcohol
+6096 // Fish_With_Blue_Back
+6097 // Pumpkin_Pie_
+6098 // Small_Snow_Flower
+6099 // Grilled_Rice_Cake
+6100 // Damp_Darkness
+6104 // Big_Cell
+6105 // Morning_Dew
+6106 // Well_Ripened_Berry
+6107 // Sunset_On_The_Rock
+6108 // Apple_Pudding
+6109 // Plant_Neutrient
+6110 // Vital_Flower
+6111 // Mystic_Stone
+6112 // Fresh_Plant
+6113 // Vital_Flower_
+6114 // Flame_Gemstone
+6115 // Bun_
+6120 // Face_Paint
+6123 // Surface_Paint
+6128 // Guillotine_Antidote
+6144 // Heartbroken_Tears
+6145 // Vulcan_Bullet
+6146 // Magic_Gear_Fuel
+6147 // Liquid_Condensed_Bullet
+6186 // Monkey_Wrench
+//6189
+//6190
+//6191
+//6192
+//6193
+//6194
+//6195
+//6196
+//6197
+//6198
+//6199
+//6200
+//6201
+//6202
+//6203
+//6204
+//6205
+//6210 // Seed_Of_Thorny_Plant
+//6211 // Bloodsuck_Plant_Seed
+//6212 // Bomb_Mushroom_Spore
+//6213 // Explosive_Powder
+//6214 // Smokes_Powder
+//6215 // Tear_Gas
+//6216 // Oil_Bottle
+//6217 // Mandragora_Flowerpot
+6223 // Carnium
+6224 // Bradium
+//6244 // Dark_Powder
+//6245 // Black_Powder
+//6246 // Yellow_Powder
+//6247 // White_Powder
+//6248 // Chowder_Pot
+//6249 // Savage_Meat
+//6250 // Iron_Cooking_Skewer
+//6251 // Black_Charcoal
+//6252 // Wolf's_Blood
+//6253 // Cold_Ice
+//6254 // Seasoned_Tough_Meat
+//6255 // Large_Pan
+//6256 // Powdered_Ice
+//6257 // Ice_Crystal
+//6258 // Comodo_Tropical_Fruit
+//6259 // Drosera_Feeler
+//6260 // Petite_Tail
+//6261 // Fine_Noodles
+//6262 // Cold_Broth
+//6263 // Coconut
+//6264 // Melon
+//6265 // Pineapple
+//6279 // Apple_Bomb_Guidebook
+//6280 // Pineapple_Bomb_Guidebook
+//6281 // Coconut_Bomb_Guidebook
+//6282 // Melon_Bomb_Guidebook
+//6283 // Banana_Bomb_Guidebook
+//6284 // Plant_Genetic_Cultivation_Guide
+//6285 // Improved_Potion_Creation_Manual
+6297 // Empty_Potion_Bottle
+//6321 // Rake_Helmet
+//6322 // Antler_Helmet
+//6323 // Two-Horn_Helmet
+//6324 // One-Horn_Helmet
+//6325 // White_Spider_Legs
+//6326 // Queen_Scraba_Shell
+//6360 // Scarlet_Point
+//6361 // Indigo_Point
+//6362 // Yellow_Wish_Point
+//6363 // Lime_Green_Point
+7001 // Mould_Powder
+7002 // Ogre_Tooth
+7003 // Anolian_Skin
+7004 // Mud_Lump
+7005 // Skull
+7006 // Wing_Of_Red_Bat
+7007 // Claw_Of_Rat
+7008 // Stiff_Horn
+7009 // Glitter_Shell
+7010 // Tail_Of_Steel_Scorpion
+7011 // Claw_Of_Monkey
+7012 // Tough_Scalelike_Stem
+7013 // Coral_Reef
+7014 // Old_Portrait
+7015 // Bookclip_In_Memory
+7016 // Spoon_Stub
+7017 // Executioner's_Mitten
+7018 // Young_Twig
+7019 // Loki's_Whispers
+7020 // Mother's_Nightmare
+7021 // Foolishness_Of_Blind
+7022 // Old_Hilt
+7023 // Blade_Lost_In_Darkness
+7024 // Bloody_Edge
+7026 // Key_Of_Clock_Tower
+7027 // Underground_Key
+7030 // Claw_Of_Desert_Wolf
+7031 // Old_Frying_Pan
+7032 // Piece_Of_Egg_Shell
+7033 // Poison_Spore
+7034 // Red_Socks_With_Holes
+7035 // Matchstick
+7036 // Fang_Of_Garm
+7038 // Yarn
+7041 // Fine_Grit
+7043 // Fine_Sand
+7047 // Alice's_Apron
+7048 // Talon_Of_Griffin
+7049 // Stone
+7053 // Cyfar
+7054 // Brigan
+7055 // Animal_Pooopoo
+7056 // Payroll_Of_Kafra
+7057 // Gallar_Horn
+7058 // Gullraifnir
+7063 // Soft_Feather
+7064 // Dragon_Fly_Wing
+7065 // Sea_Otter_Leather
+7066 // Ice_Piece
+7067 // Stone_Piece
+7068 // Burn_Tree
+7069 // Broken_Armor_Piece
+7070 // Broken_Shell
+7071 // Tatters_Clothes
+7072 // Rust_Suriken
+7073 // Jewel_Of_Prayer
+7074 // Iron_Glove
+7075 // Iron_Maiden
+7076 // Mystery_Wheel
+7077 // Silver_Fancy
+7078 // Anger_Of_Valkurye
+7079 // Feather_Of_Angel
+7080 // Foot_Step_Of_Cat
+7081 // Beard_Of_Women
+7082 // Root_Of_Stone
+7083 // Soul_Of_Fish
+7084 // Saliva_Of_Bird
+7085 // Tendon_Of_Bear
+7086 // Symbol_Of_Sun
+7087 // Breath_Of_Soul
+7088 // Crystal_Of_Snow
+7089 // Indication_Of_Tempest
+7090 // Slilince_Wave
+7091 // Rough_Billows
+7092 // Air_Stream
+7093 // Wheel
+7094 // Mystery_Piece
+7095 // Broken_Steel_Piece
+7096 // Cold_Magma
+7097 // Burning_Heart
+7098 // Live_Coal
+7099 // Old_Magic_Circle
+7100 // Sharp_Leaf
+7101 // Peco_Wing_Feather
+7102 // Hideous_Dream
+7103 // Unknown_Liquid_Bottle
+7104 // Fake_Angel_Wing
+7105 // Fake_Angel_Loop
+7106 // Goat's_Horn
+7107 // Gaoat's_Skin
+7108 // Boroken_Shiled_Piece
+7109 // Shine_Spear_Blade
+7110 // Vroken_Sword
+7111 // Smooth_Paper
+7112 // Fright_Paper_Blade
+7113 // Broken_Pharaoh_Symbol
+7114 // Tutankhamen's_Mask
+7115 // Harpy's_Feather
+7116 // Harpy's_Claw
+7117 // Rent_Spell_Book
+7118 // Rent_Scroll
+7119 // Spawns
+7120 // Burning_Horse_Shoe
+7121 // Honey_Jar
+7122 // Hot_Hair
+7123 // Dragon's_Skin
+7124 // Sand_Lump
+7125 // Scropion's_Nipper
+7126 // Large_Jellopy
+7127 // Alcol_Create_Book
+7128 // FireBottle_Create_Book
+7129 // Acid_Create_Book
+7130 // Plant_Create_Book
+7131 // Mine_Create_Book
+7132 // Coating_Create_Book
+7133 // Slim_Potion_Create_Book
+7134 // Medicine_Bowl
+7140 // Seed_Of_Life
+7141 // Yggdrasilberry_Dew
+7143 // Life_Force_Pot
+7144 // Normal_Potion_Book
+7147 // Jasmin
+7149 // Yellow_Plate
+7150 // Bamboo_Cut
+7151 // Oil_Paper
+7152 // Glossy_Hair
+7153 // Old_Japaness_Clothes
+7154 // Poison_Powder
+7155 // Poison_Toad's_Skin
+7156 // Broken_Shuriken
+7157 // Black_Mask
+7158 // Broken_Wine_Vessel
+7159 // Tengu's_Nose
+7160 // Lord's_Passable_Ticket
+7161 // Black_Bear's_Skin
+7162 // Cloud_Piece
+7163 // Sharp_Feeler
+7164 // Hard_Peach
+7165 // Limpid_Celestial_Robe
+7166 // Soft_Silk_Cloth
+7167 // Mystery_Iron_Bit
+7168 // Great_Wing
+7169 // Taegeuk_Plate
+7170 // Tuxedo
+7171 // Leopard_Skin
+7172 // Leopard_Talon
+7174 // Packing_Ribbon
+7175 // Packing_Paper
+7182 // Cacao
+7186 // Thin_Stem
+7187 // Festival_Mask
+7188 // Browny_Root
+7189 // Heart_Of_Tree
+7190 // Solid_Peeling
+7191 // Lamplight
+7192 // Blade_Of_Pinwheel
+7193 // Germinating_Sprout
+7194 // Soft_Leaf
+7195 // Air_Rifle
+7196 // Shoulder_Protection
+7197 // Tough_Vines
+7198 // Great_Leaf
+7199 // Coupon
+7200 // Flexible_String
+7201 // Log
+7202 // Beetle_Nipper
+7203 // Solid_Twig
+7204 // Gunpowder
+7205 // Piece_Of_Black_Cloth
+7206 // Black_Kitty_Doll
+7207 // Old_Manteau
+7208 // Rusty_Cleaver
+7209 // Dullahan's_Helm
+7210 // Dullahan_Armor
+7211 // Rojerta_Piece
+7212 // Hanging_Doll
+7213 // Needle_Pouch
+7214 // Bat_Cage
+7215 // Broken_Needle
+7216 // Red_Scarf
+7217 // Spool
+7218 // Rotten_Rope
+7219 // Striped_Socks
+7220 // Ectoplasm
+7221 // Tangled_Chain
+7222 // Tree_Knot
+7223 // Distorted_Portrait
+7225 // Pumpkin_Bucket
+7226 // Pill
+7262 // Fan
+7263 // Cat_Eyed_Stone
+7264 // Dried_Sand
+7265 // Dragon_Horn
+7266 // Dragon_Fang
+7267 // Tiger_Skin_Panties
+7268 // Little_Blacky_Ghost
+7269 // Bib
+7270 // Milk_Bottle
+7277 // Munak_Doll
+7286 // Chilli
+7289 // Olivine
+7290 // Phlogopite
+7291 // Agate
+7292 // Muscovite
+7293 // Rose_Quartz
+7294 // Turquoise
+7295 // Citrine
+7296 // Pyroxene
+7297 // Biotite
+7298 // Leaf_Clothes
+7299 // Bamboo_Basket
+7300 // Gemstone
+7301 // Sword_Accessory
+7303 // Bag_Of_Rice
+7312 // Jubilee
+7315 // Dark_Crystal_Fragment
+7316 // Long_Limb
+7317 // Screw
+7318 // Old_Pick
+7319 // Old_Steel_Plate
+7320 // Air_Pollutant
+7321 // Fragment_Of_Crystal
+7322 // Poisonous_Gas
+7323 // Battered_Kettle
+7325 // Tube
+7326 // Fluorescent_Liquid
+7327 // Headlamp
+7340 // Will_Of_Darkness
+7345 // Armlet_Of_Prisoner
+7352 // Transparent_Plate01
+7353 // Transparent_Plate02
+7354 // Transparent_Plate03
+7355 // Transparent_Plate04
+7356 // Piece_Of_Crest1
+7357 // Piece_Of_Crest2
+7358 // Piece_Of_Crest3
+7359 // Piece_Of_Crest4
+7419 // Embryo_HandBook
+7433 // Scroll
+7434 // Elemental_Potion_Book
+7435 // Golden_Bracelet
+7436 // Piece_Of_Memory_Green
+7437 // Piece_Of_Memory_Purple
+7438 // Piece_Of_Memory_Blue
+7439 // Piece_Of_Memory_Red
+7440 // Red_Feather
+7441 // Blue_Feather
+7442 // Cursed_Seal
+7443 // Tri_Headed_Dragon_Head
+7444 // Treasure_Box
+7445 // Dragonball_Green
+7446 // Dragonball_Blue
+7447 // Dragonball_Red
+7448 // Dragonball_Yellow
+7449 // Bloody_Page
+7450 // Piece_Of_Bone_Armor
+7451 // Scale_Of_Red_Dragon
+7452 // Yellow_Spice
+7453 // Sweet_Sauce
+7454 // Plain_Sauce
+7455 // Hot_Sauce
+7456 // Red_Spice
+7457 // Cooking_Oil
+7472 // Cookbook01
+7473 // Cookbook02
+7474 // Cookbook03
+7475 // Cookbook04
+7476 // Cookbook05
+7477 // Cookbook06
+7478 // Cookbook07
+7479 // Cookbook08
+7480 // Cookbook09
+7481 // Cookbook10
+7482 // Pot
+7507 // Sturdy_Iron_Piece
+7510 // Valhalla_Flower
+7511 // Rune_Of_Darkness
+7512 // Burnt_Parts
+7513 // Pocket_Watch
+7521 // Flame_Stone
+7522 // Ice_Stone
+7523 // Wind_Stone
+7524 // Shadow_Orb
+7561 // Ice_Heart
+7562 // Ice_Scale
+7563 // Bloody_Rune
+7564 // Rotten_Meat
+7565 // Sticky_Poison
+7566 // Will_Of_Darkness_
+7567 // Suspicious_Hat
+7568 // White_Mask
+7574 // Ice_Particle
+7751 // Old_White_Cloth
+7752 // Clattering_Skull
+7753 // Broken_Farming_Utensil
+7754 // Broken_Crown
+7830 // Goddess_Tear
+7831 // Valkyrie_Token
+7832 // Brynhild_Armor_Piece
+7833 // Hero_Remains
+7834 // Andvari_Ring
+7835 // Dusk_Glow
+7836 // Dawn_Essence
+7837 // Cold_Moonlight
+7838 // Hazy_Starlight
+7931 // Poison_Kit
+7932 // Poison_Herb_Nerium
+7933 // Poison_Herb_Rantana
+7934 // Poison_Herb_Makulata
+7935 // Poison_Herb_Seratum
+7936 // Poison_Herb_Scopolia
+7937 // Poison_Herb_Amoena
+7938 // Light_Granule
+7939 // Elder_Branch
+7940 // Special_Alloy_Trap
+11000 // Prontera_Book_01
+11001 // Adventure_Story01
+11002 // Great_Chef_Orleans01
+11003 // Legend_Of_Kafra01
+11004 // Mercenary_Rebellion
+11005 // Tyrant_Schmidt
+11006 // Blood_Flower01
+11007 // Blood_Flower02
+11008 // Barmund
+11009 // Adventure_Story02
+//11020
+//11021
+//11022 // Mix_Cooking_Ingredient_Book_1
+//11023 // Vitality_Boost_Research_Book
+//11024 // Energy_Drink_Formula
+
diff --git a/db/item_db.txt b/db/item_db.txt
index 0b2455ce9..1087c30cb 100644
--- a/db/item_db.txt
+++ b/db/item_db.txt
@@ -684,7 +684,7 @@
1382,Krieger_Twohand_Axe1,Glorious Two-Handed Axe,4,0,,0,220,,1,0,0x000444A2,7,2,34,4,80,1,7,{ bonus2 bAddRace,RC_DemiHuman,70; bonus2 bIgnoreDefRate,RC_DemiHuman,20; bonus bUnbreakableWeapon,0; if(getrefine() > 5) { bonus2 bAddRace,RC_DemiHuman,(getrefine()-3)*(getrefine()-3); bonus2 bIgnoreDefRate,RC_DemiHuman,5; bonus3 bAutoSpell,"NPC_CRITICALWOUND",1,50; } if(getrefine() > 8) { bonus3 bAutoSpell,"NPC_CRITICALWOUND",1,100; bonus4 bAutoSpellOnSkill,"MC_MAMMONITE","NPC_CRITICALWOUND",2,200; bonus4 bAutoSpellOnSkill,"WS_CARTTERMINATION","NPC_CRITICALWOUND",2,200; } },{},{}
1383,Holy_Celestial_Axe,Celestial Axe,4,0,,1500,250,,1,0,0x000444A2,7,2,34,4,60,1,7,{ bonus2 bAddRace,RC_Undead,10; bonus3 bAutoSpell,"AL_BLESSING",5,50; },{},{}
1384,Veteran_Axe,Veteran Axe,4,0,,3000,250,,1,2,0x000444A2,7,2,34,3,80,1,7,{ if(getskilllv("BS_DAGGER")==3) { bonus bAtk,10; } if(getskilllv("BS_SWORD")==3) { bonus bAtk,10; } if(getskilllv("BS_TWOHANDSWORD")==3) { bonus bAtk,10; } if(getskilllv("BS_KNUCKLE")==3) { bonus bAtk,10; } if(getskilllv("BS_SPEAR")==3) { bonus bAtk,10; } if(getskilllv("BS_AXE")==3) { bonus bAtk,10; } if(getskilllv("BS_MACE")==3) { bonus bAtk,10; } bonus bVit,2; },{},{}
-1385,Bradium_Stonehammer,Bradium Stone Hammer,4,0,,2700,210,,1,0,0x000444A2,2,2,34,4,75,1,7,{ bonus3 bAddEffOnSkill,"BS_HAMMERFALL",Eff_Stun,50+(20*getrefine()); },{},{}
+1385,Bradium_Stonehammer,Bradium Stone Hammer,4,0,,2700,210,,1,0,0x000444A2,2,2,34,4,75,1,7,{ bonus3 bAddEffOnSkill,"BS_HAMMERFALL",Eff_Stun,500+(200*getrefine()); },{},{}
1386,Doom_Slayer_I,Doom Slayer,4,20,,0,20,,1,0,0x000444A2,7,2,34,4,0,0,7,{ if(readparam(bStr)>=95){ bonus bBaseAtk,400; bonus2 bAddEff,Eff_Stun,3000; bonus bAspdRate,-25; bonus bUseSPrate,100; bonus bBreakArmorRate,500; } },{},{}
1387,Giant_Axe,Giant Axe,4,0,,4000,330,,1,1,0x000444A2,2,2,34,3,50,1,7,{ bonus2 bSkillAtk,"WS_CARTTERMINATION",15; if(readparam(bStr)>=95) { bonus bHit,10; bonus bAspdRate,3; } },{},{}
1388,Two_Handed_Axe_C,Two-Handed Axe,4,0,,0,220,,1,0,0x000444A2,7,2,34,3,1,0,7,{ bonus2 bAddSize,0,40; bonus2 bAddSize,1,40; bonus2 bAddSize,2,40; },{},{}
@@ -1024,7 +1024,7 @@
1923,BF_Instrument1,Valorous Battlefield Guitar,4,0,,0,50,,1,0,0x00080000,7,1,2,3,80,1,13,{ bonus bDex,2; bonus2 bAddRace,RC_DemiHuman,95; bonus2 bIgnoreDefRate,RC_DemiHuman,20; bonus bUnbreakableWeapon,0; },{},{}
1924,BF_Instrument2,Brave Battlefield Guitar,4,0,,0,50,,1,0,0x00080000,7,1,2,3,80,1,13,{ bonus bDex,2; bonus2 bAddRace,RC_DemiHuman,95; bonus2 bSkillAtk,"CG_ARROWVULCAN",20; bonus bUnbreakableWeapon,0; },{},{}
1925,Chello,Cello,4,20,,700,110,,1,3,0x00080000,2,1,002,3,70,1,13,{ bonus bAgi,2; bonus bDex,3; bonus2 bAddSkillBlow,"BA_MUSICALSTRIKE",2; bonus2 bAddSkillBlow,"CG_ARROWVULCAN",3; },{},{}
-1926,Harp_Of_Nepenthes,Harp of Nepenthes,4,20,,1000,120,,1,2,0x00080000,2,1,2,4,60,1,13,{ bonus bInt,2; bonus3 bAddEffOnSkill,"BA_MUSICALSTRIKE",Eff_Stun,100; if( getrefine() > 9 ) { bonus3 bAddEffOnSkill,"BA_MUSICALSTRIKE",Eff_Stun,200; } },{},{}
+1926,Harp_Of_Nepenthes,Harp of Nepenthes,4,20,,1000,120,,1,2,0x00080000,2,1,2,4,60,1,13,{ bonus bInt,2; if( getrefine() > 9 ) { bonus3 bAddEffOnSkill,"BA_MUSICALSTRIKE",Eff_Stun,2000; } else { bonus3 bAddEffOnSkill,"BA_MUSICALSTRIKE",Eff_Stun,1000; } },{},{}
1927,Krieger_Instrument1,Glorious Guitar,4,0,,0,50,,1,0,0x00180000,7,1,2,4,80,1,13,{ bonus2 bAddRace,RC_DemiHuman,95; bonus2 bIgnoreDefRate,RC_DemiHuman,20; bonus bUnbreakableWeapon,0; if(getrefine() > 5) { bonus2 bAddRace,RC_DemiHuman,(getrefine()-4)*(getrefine()-4); bonus2 bIgnoreDefRate,RC_DemiHuman,5; } if(getrefine() > 8) bonus4 bAutoSpellOnSkill,"CG_ARROWVULCAN","CG_TAROTCARD",5,100; },{},{}
1928,Berserk_Guitar_I,Spirited Guitar,4,0,,0,40,,1,0,0x00080000,2,1,2,4,0,1,13,{ bonus bAspdRate,100; bonus bHPrecovRate,-100; bonus2 bHPLossRate,50,5000; bonus bDex,-readparam(bDex); },{},{}
1929,Guitar_C,Guitar,4,0,,0,177,,1,0,0x00080000,7,1,2,3,1,0,13,{ bonus2 bAddSize,0,40; bonus2 bAddSize,1,40; bonus2 bAddSize,2,40; },{},{}
@@ -1058,7 +1058,7 @@
1976,Queen's_Whip_,Queen's Whip,4,20,,1100,150,,2,2,0x00080000,7,0,2,4,65,1,14,{ bonus2 bSkillAtk,"CG_ARROWVULCAN",10; bonus2 bSkillAtk,"DC_THROWARROW",10; },{},{}
1977,BF_Whip1,Valorous Battle Lariat,4,0,,0,50,,2,0,0x00080000,7,0,2,3,80,1,14,{ bonus bDex,2; bonus2 bAddRace,RC_DemiHuman,95; bonus2 bIgnoreDefRate,RC_DemiHuman,20; bonus bUnbreakableWeapon,0; },{},{}
1978,BF_Whip2,Brave Battle Lariat,4,0,,0,50,,2,0,0x00080000,7,0,2,3,80,1,14,{ bonus bDex,2; bonus2 bAddRace,RC_DemiHuman,95; bonus2 bSkillAtk,"CG_ARROWVULCAN",20; bonus bUnbreakableWeapon,0; },{},{}
-1979,Stem_Of_Nepenthes,Stem of Nepenthes,4,20,,1000,120,,1,2,0x00080000,2,0,2,4,60,1,14,{ bonus bInt,2; bonus3 bAddEffOnSkill,"DC_THROWARROW",Eff_Freeze,100; if( getrefine() >= 9 ) { bonus3 bAddEffOnSkill,"DC_THROWARROW",Eff_Freeze,200; } },{},{}
+1979,Stem_Of_Nepenthes,Stem of Nepenthes,4,20,,1000,120,,1,2,0x00080000,2,0,2,4,60,1,14,{ bonus bInt,2; if( getrefine() >= 9 ) { bonus3 bAddEffOnSkill,"DC_THROWARROW",Eff_Freeze,2000; } else { bonus3 bAddEffOnSkill,"DC_THROWARROW",Eff_Freeze,1000; } },{},{}
1980,Whip_Of_Balance,Whip of Balance,4,20,,700,110,,1,3,0x00080000,2,0,2,3,70,1,14,{ bonus bAgi,2; bonus bDex,3; bonus2 bAddSkillBlow,"DC_THROWARROW",2; bonus2 bAddSkillBlow,"CG_ARROWVULCAN",3; },{},{}
1981,Krieger_Whip1,Glorious Lariat,4,0,,0,50,,2,0,0x00180000,7,0,2,4,80,1,14,{ bonus2 bAddRace,RC_DemiHuman,95; bonus2 bIgnoreDefRate,RC_DemiHuman,20; bonus bUnbreakableWeapon,0; if(getrefine() > 5) { bonus2 bAddRace,RC_DemiHuman,(getrefine()-4)*(getrefine()-4); bonus2 bIgnoreDefRate,RC_DemiHuman,5; } if(getrefine() > 8) bonus4 bAutoSpellOnSkill,"CG_ARROWVULCAN","CG_TAROTCARD",5,100; },{},{}
1982,Phenomena_Whip,Phenomena Whip,4,0,,0,160,,2,0,0x00080000,7,0,2,4,1,0,14,{ bonus2 bSkillAtk,"DC_THROWARROW",25; },{},{}
@@ -2763,7 +2763,7 @@
5555,Leaf_Cat_Hat,Leaf Cat Hat,5,20,,100,,3,,0,0xFFFFFFFF,7,2,256,,0,1,539,{ bonus bAgi,1; bonus3 bAutoSpellWhenHit,"AL_HEAL",3,10; },{},{}
5556,Seal_Hat,Seal Hat,5,20,,500,,3,,0,0xFFFFFFFF,7,2,769,,55,1,540,{ bonus bInt,1; bonus3 bAutoSpell,"WZ_FROSTNOVA",1,30; },{},{}
//5557,Wild_Rose_Hat,Wild Rose Hat,5,20,,500,,3,,1,0xFFFFFFFE,7,2,256,,20,1,541,{ bonus bAgi,3; },{},{}
-//5558,Luxury_Hat,Luxury Hat,5,20,,100,,3,,1,0xFFFFFFFF,7,2,256,,30,1,542,{ bonus3 bAddMonsterDropItem,511,RC_Plant,500; },{},{}
+//5558,Luxury_Hat,Luxury Hat,5,20,,100,,3,,1,0xFFFFFFFF,7,2,256,,30,1,542,{ bonus3 bAddMonsterDropItem,510,RC_Plant,500; },{},{}
5559,Piece_Of_White_Cloth,Piece Of White Cloth,5,20,,100,,1,,0,0xFFFFFFFF,7,2,256,,0,1,543,{},{},{}
5560,Bullock_Helm_,Bullock Helm,5,20,,300,,3,,0,0xFFFFFFFF,7,2,256,,75,1,322,{ bonus bMaxHP,100; bonus bNoKnockback,0; bonus2 bSubEle,Ele_Neutral,-20; bonus2 bSubEle,Ele_Fire,-20; bonus2 bSubEle,Ele_Water,-20; bonus2 bSubEle,Ele_Wind,-20; bonus2 bSubEle,Ele_Earth,-20; bonus2 bSubEle,Ele_Dark,-20; bonus2 bSubEle,Ele_Holy,-20; bonus2 bSubEle,Ele_Ghost,-20; },{},{}
5561,Magic_Rabbit_Hat,Magic Rabbit Hat,5,20,,800,,1,,0,0xFFFFFFFF,7,2,256,,0,1,497,{ bonus bInt,1; bonus bMaxSP,50; bonus4 bAutoSpellWhenHit,"MG_FIREBOLT",3,10,3; bonus4 bAutoSpellWhenHit,"MG_COLDBOLT",3,10,3; bonus4 bAutoSpellWhenHit,"MG_LIGHTNINGBOLT",3,10,3; bonus3 bAutoSpellWhenHit,"AL_HEAL",1,10; },{},{}
@@ -3293,7 +3293,7 @@
//6362,Yellow_Wish_Point,Yellow Wish Point,3,100,,5,,,,,,,,,,,,,{},{},{}
//6363,Lime_Green_Point,Lime Green Point,3,100,,5,,,,,,,,,,,,,{},{},{}
//6376,KVM_Badge
-//6377,Buy_Stall_Permit,Purchase Street Stall License,3,200,,10,,,,,,,,,,,,,{},{},{}
+6377,Buy_Stall_Permit,Purchase Street Stall License,3,200,,10,,,,,,,,,,,,,{},{},{}
//6378
//6379
//6380
@@ -4823,13 +4823,16 @@
//12471,LV5_Adrenaline_Scroll,
//12472,Convex_Mirror,
//12475,Cure_Free,
-//12548,Shabby_Purchase_Street_Stall_License,
+12548,Shabby_Purchase_Street_Stall_License,Shabby Purchase Street Stall License,2,500,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ buyingstore 2; },{},{}
//12553,Brysingamen_Piece_Box,
//12554,Asprika_Piece_Box,
//12555,Brynhild_Piece_Box,
//12556,Sleipnir_Piece_Box,
//12557,Mjolnir_Piece_Box,
//12558,Megingiorde_Piece_Box,
+12580,Universal_Catalog_Silver,Universal Catalog Silver,2,200,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ searchstores 10,0; },{},{}
+12581,Universal_Catalog_Gold,Universal Catalog Gold,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ searchstores 10,1; },{},{}
+12591,Universal_Catalog_Bronze,Universal Catalog Bronze,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ searchstores 10,1; },{},{}
12701,Old_Blue_Box_F,Old Blue Box,2,,,200,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{}
12702,Old_Bleu_Box,Old Navy Box,2,0,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem groupranditem(IG_BleuBox),1; getitem groupranditem(IG_BleuBox),1; },{},{}
12703,Holy_Egg_2,Holy Egg,11,0,,50,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{}
@@ -5025,8 +5028,8 @@
//13043,Fortune_Sword_I
//13044,House_Auger_I
//13045,Kamaitachi_I
-13046,Krieg,Krierg,4,20,,500,110,,1,3,0x00021040,2,2,2,2,50,1,1,{ bonus3 bAddEffOnSkill,"RG_BACKSTAP",Eff_Bleeding,100; bonus2 bSkillAtk,"RG_BACKSTAP",15; },{},{}
-13047,Weihna,Weihna,4,20,,500,135,,1,2,0x00021040,2,2,2,3,50,1,1,{ bonus3 bAddEffOnSkill,"RG_RAID",Eff_Poison,100; autobonus "{ bonus2 bAddRace,RC_NonBoss,10; bonus2 bAddRace,RC_Boss,10; }",5,5000,BF_WEAPON|BF_SHORT,"{ specialeffect2 EF_POTION_BERSERK; }"; },{},{}
+13046,Krieg,Krierg,4,20,,500,110,,1,3,0x00021040,2,2,2,2,50,1,1,{ bonus3 bAddEffOnSkill,"RG_BACKSTAP",Eff_Bleeding,1000; bonus2 bSkillAtk,"RG_BACKSTAP",15; },{},{}
+13047,Weihna,Weihna,4,20,,500,135,,1,2,0x00021040,2,2,2,3,50,1,1,{ bonus3 bAddEffOnSkill,"RG_RAID",Eff_Poison,1000; autobonus "{ bonus2 bAddRace,RC_NonBoss,10; bonus2 bAddRace,RC_Boss,10; }",5,5000,BF_WEAPON|BF_SHORT,"{ specialeffect2 EF_POTION_BERSERK; }"; },{},{}
//13048,Damascus_C
13050,P_Dagger1,Eden Dagger I,4,0,,0,124,,1,0,0xFE9F7EEF,7,2,2,2,26,0,1,{},{},{}
13051,P_Dagger2,Eden Dagger II,4,0,,0,158,,1,0,0xFE9F7EEF,7,2,2,2,40,0,1,{},{},{}
@@ -5077,8 +5080,8 @@
//13175,Lever_Action_Rifle_C
13176,Krieger_Rifle1,Glorious Rifle,4,0,,0,90,,9,0,0x01000000,7,2,34,4,80,1,18,{ bonus2 bAddRace,RC_DemiHuman,75; bonus2 bIgnoreDefRate,RC_DemiHuman,20; bonus2 bSkillAtk,"GS_TRIPLEACTION",30; bonus bUnbreakableWeapon,0; if(getrefine() > 5) { bonus2 bAddRace,RC_DemiHuman,(getrefine()-4)*(getrefine()-4); bonus2 bIgnoreDefRate,RC_DemiHuman,5; } if(getrefine() > 8) { bonus2 bCastrate,"GS_TRACKING",25; bonus2 bSkillAtk,"GS_TRACKING",getrefine() * 3; } },{},{}
13177,Krieger_Gatling1,Glorious Gatling Gun,4,0,,0,90,,9,0,0x01000000,7,2,34,4,80,1,19,{ bonus2 bAddRace,RC_DemiHuman,35; bonus2 bIgnoreDefRate,RC_DemiHuman,25; bonus2 bSkillAtk,"GS_TRIPLEACTION",30; bonus bUnbreakableWeapon,0; if(getrefine() > 5) { bonus2 bAddRace,RC_DemiHuman,(getrefine()-4)*(getrefine()-4); bonus2 bIgnoreDefRate,RC_DemiHuman,5; } if(getrefine() > 8) {bonus2 bAddRace,RC_Boss,getrefine(); bonus2 bAddRace,RC_NonBoss,getrefine(); } },{},{}
-13178,Krieger_Shotgun1,Glorious Shotgun,4,0,,0,110,,9,0,0x01000000,7,2,34,4,80,1,20,{ bonus2 bAddRace,RC_DemiHuman,55; bonus2 bIgnoreDefRate,RC_DemiHuman,20; bonus bSplashRange,1; bonus2 bSkillAtk,"GS_TRIPLEACTION",30; bonus bUnbreakableWeapon,0; if(getrefine() > 5) { bonus2 bAddRace,RC_DemiHuman,(getrefine()-4)*(getrefine()-4); bonus2 bIgnoreDefRate,RC_DemiHuman,5; } if(getrefine() > 8) { bonus2 bSkillAtk,"GS_SPREADATTACK",getrefine() * 2; bonus3 bAddEffOnSkill,"GS_SPREADATTACK",Eff_Stun,200; } },{},{}
-13179,Krieger_Launcher1,Glorious Grenade Launcher,4,0,,0,330,,9,0,0x01000000,7,2,34,4,80,1,21,{ bonus2 bAddRace,RC_DemiHuman,35; bonus2 bIgnoreDefRate,RC_DemiHuman,20; bonus2 bSkillAtk,"GS_TRIPLEACTION",30; bonus bUnbreakableWeapon,0; if(getrefine() > 5) { bonus2 bAddRace,RC_DemiHuman,(getrefine()-4)*(getrefine()-4); bonus2 bIgnoreDefRate,RC_DemiHuman,5; } if(getrefine() > 8) { bonus2 bSkillAtk,"GS_GROUNDDRIFT",getrefine() * 2; bonus3 bAddEffOnSkill,"GS_SPREADATTACK",Eff_Stun,200; autobonus "{ bonus bAspdRate,20; }",200,20000,BF_WEAPON,"{ specialeffect2 EF_POTION_BERSERK; }"; } },{},{}
+13178,Krieger_Shotgun1,Glorious Shotgun,4,0,,0,110,,9,0,0x01000000,7,2,34,4,80,1,20,{ bonus2 bAddRace,RC_DemiHuman,55; bonus2 bIgnoreDefRate,RC_DemiHuman,20; bonus bSplashRange,1; bonus2 bSkillAtk,"GS_TRIPLEACTION",30; bonus bUnbreakableWeapon,0; if(getrefine() > 5) { bonus2 bAddRace,RC_DemiHuman,(getrefine()-4)*(getrefine()-4); bonus2 bIgnoreDefRate,RC_DemiHuman,5; } if(getrefine() > 8) { bonus2 bSkillAtk,"GS_SPREADATTACK",getrefine() * 2; bonus3 bAddEffOnSkill,"GS_SPREADATTACK",Eff_Stun,2000; } },{},{}
+13179,Krieger_Launcher1,Glorious Grenade Launcher,4,0,,0,330,,9,0,0x01000000,7,2,34,4,80,1,21,{ bonus2 bAddRace,RC_DemiHuman,35; bonus2 bIgnoreDefRate,RC_DemiHuman,20; bonus2 bSkillAtk,"GS_TRIPLEACTION",30; bonus bUnbreakableWeapon,0; if(getrefine() > 5) { bonus2 bAddRace,RC_DemiHuman,(getrefine()-4)*(getrefine()-4); bonus2 bIgnoreDefRate,RC_DemiHuman,5; } if(getrefine() > 8) { bonus2 bSkillAtk,"GS_GROUNDDRIFT",getrefine() * 2; bonus3 bAddEffOnSkill,"GS_SPREADATTACK",Eff_Stun,2000; autobonus "{ bonus bAspdRate,20; }",200,20000,BF_WEAPON,"{ specialeffect2 EF_POTION_BERSERK; }"; } },{},{}
// Bullets
13200,Bullet,Bullet,10,1,,2,10,,,,0x01000000,7,2,32768,,1,,3,{},{},{}
13201,Silver_Bullet,Silver Bullet,10,15,,2,15,,,,0x01000000,7,2,32768,,1,,3,{ bonus bAtkEle,Ele_Holy; },{},{}
@@ -6183,6 +6186,12 @@
//16588,Thoughtful_Hat_Box
//16589,Thoughtful_Hat_Box
//16590,Thoughtful_Hat_Box
+16677,Universal_Catalog_Gold_Box10,Universal Catalog Gold 10 Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 12581,10; },{},{}
+16678,Universal_Catalog_Gold_Box50,Universal Catalog Gold 50 Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 12581,50; },{},{}
+16679,Universal_Catalog_Gold_Box10,Universal Catalog Gold 10 Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 12581,10; },{},{}
+16680,Universal_Catalog_Gold_Box50,Universal Catalog Gold 50 Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 12581,50; },{},{}
+16776,Universal_Catalog_Gold_Box10,Universal Catalog Gold 10 Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 12581,10; },{},{}
+16777,Universal_Catalog_Gold_Box50,Universal Catalog Gold 50 Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 12581,50; },{},{}
//18000,Cannon_Ball
//18001,Holy_Cannon_Ball
//18002,Dark_Cannon_Ball
diff --git a/db/packet_db.txt b/db/packet_db.txt
index 763aa96a8..61fb2e75a 100644
--- a/db/packet_db.txt
+++ b/db/packet_db.txt
@@ -1487,8 +1487,8 @@ packet_ver: 25
0x080F,20
//2010-03-03aRagexeRE
-//0x0810,3
-//0x0811,-1
+0x0810,3
+0x0811,-1,reqopenbuyingstore,2:4:8:9:89
//0x0812,86
//0x0813,6
//0x0814,6
@@ -1498,11 +1498,11 @@ packet_ver: 25
//0x0819,4
//2010-03-09aRagexeRE
-//0x0813,-1
+0x0813,-1
//0x0814,2
//0x0815,6
-//0x0816,6
-//0x0818,-1
+0x0816,6
+0x0818,-1
//0x0819,10
//0x081A,4
//0x081B,4
@@ -1527,31 +1527,30 @@ packet_ver: 25
//0x081B,8
//2010-04-20aRagexeRE
-//0x0812,8
-//0x0814,86
-//0x0815,2
-//0x0817,6
-//0x0819,-1
-//0x081a,4
-//0x081b,10
-//0x081c,10
-//0x0824,6
+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
-//0x0836,-1
-//0x0837,3
+0x0835,-1,searchstoreinfo,2:4:5:9:13:14:15
+0x0836,-1
+0x0837,3
//0x0838,3
//2010-06-08aRagexeRE
-//0x0838,2
-//0x0839,66
-//0x083A,4 // Search Stalls Feature
-//0x083B,2
-//0x083C,12
-//0x083D,6
+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
@@ -1566,7 +1565,7 @@ packet_ver: 25
//0x07F3,6
//2010-07-01aRagexeRE
-//0x083A,5 // Search Stalls Feature
+0x083A,5 // Search Stalls Feature
//2010-07-13aRagexeRE
//0x0827,6
@@ -1582,6 +1581,7 @@ packet_ver: 25
//0x841,4
//2010-08-03aRagexeRE
+0x0839,66
0x0842,6,recall2,2
0x0843,6,remove2,2
diff --git a/db/skill_db.txt b/db/skill_db.txt
index b534986c8..2a39740df 100644
--- a/db/skill_db.txt
+++ b/db/skill_db.txt
@@ -938,6 +938,9 @@
// Episode 13.3
//2534,0,0,0,0,0,0,9,0,no,0,0,0,none,0 RETURN_TO_ELDICASTES,
+// Buying Store
+2535,0,0,4,0,0x1,0,1,0,no,0,0x1,0,none,0, ALL_BUYING_STORE,Open Buying Store
+
8001,9,6,4,0,0x1,0,5,1,no,0,0,0,magic,0, HLIF_HEAL,Healing Touch
8002,0,6,4,0,0x3,-1,5,1,no,0,0,0,none,0, HLIF_AVOID,Avoid
8003,0,0,0,0,0,1,5,0,no,0,0,0,none,0, HLIF_BRAIN,Brain Surgery
diff --git a/db/skill_nocast_db.txt b/db/skill_nocast_db.txt
index f52324d0e..47ec1226b 100644
--- a/db/skill_nocast_db.txt
+++ b/db/skill_nocast_db.txt
@@ -39,12 +39,14 @@
27,8 //AL_WARP
87,8 //WZ_ICEWALL
150,8 //TF_BACKSLIDING
+264,8 //MO_BODYRELOCATION
361,8 //HP_ASSUMPTIO
362,8 //HP_BASILICA
395,8 //CG_MOONLIT
+396,8 //CG_MARIONETTE
491,8 //CR_CULTIVATION
411,8 //TK_RUN
-426,8 //High Jump
+426,8 //TK_HIGHJUMP
427,8 //SG_FEEL
428,8 //SG_SUN_WARM
429,8 //SG_MOON_WARM
@@ -59,6 +61,7 @@
438,8 //SG_SUN_BLESS
439,8 //SG_MOON_BLESS
440,8 //SG_STAR_BLESS
+530,8 //NJ_KIRIKAGE
691,8 //CASH_ASSUMPITO
//mixed
@@ -69,34 +72,41 @@
79,16 //PR_MAGNUS
//Zone 1 - Aldebaran Turbo Track
-219,32 //Snatch
-26,32 //Teleport
-27,32 //Warp portal
-51,32 //Hiding
-135,32 //Cloaking
-389,32 //Stealth
-35,32 //Cure
-87,32 //Ice Wall
-359,32 //Berserk (Frenzy)
-362,32 //Basilica
-395,32 //Sheltering Bliss
-357,32 //Spear Dynamo (Concentration)
-264,32 //Snap (Body Relocation)
+219,32 //RG_INTIMIDATE
+26,32 //AL_TELEPORT
+27,32 //AL_WARP
+51,32 //TF_HIDING
+135,32 //AS_CLOAKING
+389,32 //ST_CHASEWALK
+35,32 //AL_CURE
+87,32 //WZ_ICEWALL
+359,32 //LK_BERSERK
+362,32 //HP_BASILICA
+395,32 //CG_MOONLIT
+357,32 //LK_CONCENTRATION
+264,32 //MO_BODYRELOCATION
//Zone 2 - Jail
-421,64 //TK_JUMPKICK#Flying Side Kick#
-426,64 //TK_HIGHJUMP#Taekwon Jump#
+421,64 //TK_JUMPKICK
+426,64 //TK_HIGHJUMP
//Zone 3 - Izlude Battle Arena
-219,128 //Snatch
-26,128 //Teleport
+219,128 //RG_INTIMIDATE
+26,128 //AL_TELEPORT
//Zone 4 - WoE:SE
-426,256 //High Jump
+426,256 //TK_HIGHJUMP
//Zone 5 - Sealed Shrine
12,512 //MG_SAFETYWALL
26,512 //AL_TELEPORT
-219,512 //Snatch
+219,512 //RG_INTIMIDATE
361,512 //HP_ASSUMPTIO
691,512 //CASH_ASSUMPTIO
+
+//Zone 6 -Endless Tower
+26,1024 //AL_TELEPORT
+87,1024 //WZ_ICEWALL
+219,1024 //RG_INTIMIDATE
+405,1024 //PF_SPIDERWEB
+674,1024 //NPC_EXPULSION
diff --git a/db/skill_require_db.txt b/db/skill_require_db.txt
index 6a81951ff..d9fa49e0e 100644
--- a/db/skill_require_db.txt
+++ b/db/skill_require_db.txt
@@ -454,6 +454,8 @@
1018,0,0,30,0,0,0,99,0,0,none,0,12114,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SA_ELEMENTFIRE
1019,0,0,30,0,0,0,99,0,0,none,0,12117,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SA_ELEMENTWIND
+2535,0,0,1,0,0,0,99,0,0,none,0,6377,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store
+
10010,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_BATTLEORDER##
10011,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_REGENERATION##
10012,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_RESTORE##
diff --git a/db/skill_tree.txt b/db/skill_tree.txt
index d64f1fef7..27f616c11 100644
--- a/db/skill_tree.txt
+++ b/db/skill_tree.txt
@@ -86,6 +86,7 @@
5,155,1,0,0,0,0,0,0,0,0,0,0 //MC_LOUD#Crazy Uproar#
5,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#
5,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
+5,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
//Thief
6,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
6,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
@@ -240,6 +241,7 @@
10,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#
10,459,1,111,5,0,0,0,0,0,0,0,0 //BS_ADRENALINE2#Full Adrenaline Rush#
10,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
+10,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
//Hunter
11,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
11,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
@@ -511,6 +513,7 @@
18,497,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT2#Twilight Alchemy 2#
18,498,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT3#Twilight Alchemy 3#
18,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
+18,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
//Bard
19,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
19,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
@@ -668,6 +671,7 @@
23,53,1,52,3,0,0,0,0,0,0,0,0 //TF_DETOXIFY#Detoxify#
23,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#
23,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
+23,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
//Gunslinger
24,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
24,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
@@ -810,6 +814,7 @@
4006,155,1,0,0,0,0,0,0,0,0,0,0 //MC_LOUD#Crazy Uproar#
4006,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#
4006,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
+4006,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
//ThiefHigh
4007,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
4007,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
@@ -989,6 +994,7 @@
4011,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#
4011,459,1,111,5,0,0,0,0,0,0,0,0 //BS_ADRENALINE2#Full Adrenaline Rush#
4011,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
+4011,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
//Sniper
4012,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
4012,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
@@ -1303,6 +1309,7 @@
4019,497,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT2#Twilight Alchemy 2#
4019,498,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT3#Twilight Alchemy 3#
4019,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
+4019,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
//Clown
4020,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
4020,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
@@ -1508,6 +1515,7 @@
4028,408,1,0,0,0,0,0,0,0,0,0,0 //WE_BABY#Baby#
4028,409,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLPARENT#Call Parent#
4028,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
+4028,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
//Baby Thief
4029,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
4029,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
@@ -1666,6 +1674,7 @@
4033,1013,1,0,0,0,0,0,0,0,0,0,0 //BS_GREED#Greed#
4033,459,1,111,5,0,0,0,0,0,0,0,0 //BS_ADRENALINE2#Full Adrenaline Rush#
4033,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
+4033,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
//Baby Hunter
4034,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
4034,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
@@ -1945,6 +1954,7 @@
4041,497,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT2#Twilight Alchemy 2#
4041,498,1,228,10,0,0,0,0,0,0,0,0 //AM_TWILIGHT3#Twilight Alchemy 3#
4041,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
+4041,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
//Baby Bard
4042,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
4042,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
@@ -2099,6 +2109,7 @@
4045,408,1,0,0,0,0,0,0,0,0,0,0 //WE_BABY#Baby#
4045,409,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLPARENT#Call Parent#
4045,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
+4045,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store#
//Taekwon
4046,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill#
4046,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid#
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index edca5e037..6afc94444 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -4,7 +4,7 @@
//= A reference manual for the eAthena scripting language.
//= Commands are sorted depending on their functionality.
//===== Version ===========================================
-//= 3.35.20110106
+//= 3.37.20110306
//=========================================================
//= 1.0 - First release, filled will as much info as I could
//= remember or figure out, most likely there are errors,
@@ -155,6 +155,10 @@
//= Spellcheck. [Ai4rei]
//= 3.35.20110106
//= Removed bug warning from 'deletearray'. [Ai4rei]
+//= 3.36.20110219
+//= Added 'buyingstore' command. [Ai4rei]
+//= 3.37.20110306
+//= Added 'searchstores' command. [Ai4rei]
//=========================================================
This document is a reference manual for all the scripting commands and functions
@@ -4424,6 +4428,39 @@ Example(s):
autoequip 1104,0;
---------------------------------------
+
+*buyingstore <slots>;
+
+Invokes buying store preparation window like the skill 'Open Buying Store',
+without the item requirement. Amount of slots is limited by the server to
+a maximum of 5 slots by default.
+
+Example:
+
+ // Gives the player oppurtunity to buy 4 different kinds of items.
+ buyingstore 4;
+
+---------------------------------------
+
+*searchstores <uses>,<effect>;
+
+Invokes the store search window, which allows to search for both vending
+and buying stores. Parameter uses indicates, how many searches can be
+started, before the window has to be reopened. Effect value affects,
+what happens, when a result item is double-clicked and can be one of the
+following:
+
+ 0 = Shows the store's position on the mini-map and highlights the
+ shop sign with yellow color, when the store is on same map
+ as the invoking player.
+ 1 = Directly opens the shop, regardless of distance.
+
+Example:
+
+ // Item Universal_Catalog_Gold (10 uses, effect: open shop)
+ searchstores 10,1;
+
+---------------------------------------
//
4,1.- End of item-related commands
//
@@ -6098,7 +6135,7 @@ illustration without displaying a new one, an empty file name and position 255
must be used.
// Displays the Comodo Kafra illustration in lower right corner.
- cutin "kafra_7",2;
+ cutin "kafra_07",2;
// Typical way to end a script, which displayed an illustration during a
// dialog with a player.
diff --git a/npc/Changelog.txt b/npc/Changelog.txt
index 2af9a0613..b0b1e3f3f 100644
--- a/npc/Changelog.txt
+++ b/npc/Changelog.txt
@@ -1,5 +1,17 @@
Date Added
======
+2011/02/06
+ * Rev. 14697 Script bug fixing. :] Here's some. I know it's been awhile. [L0ne_W0lf]
+ - Changed some duplicates so they use a floating NPC as their original. (bugreport:1395)
+ - Fixed the NPC looking for missing label in the Cursed Spirit quest. (bugreport:4654)
+ - Applied Uno's fix for the cooldown condition in Endless Tower. (bugreport:4677)
+ - Removed level requirement for the Viens Stone gathering quest. (bugreport:4678)
+ - Added the missing restricted skills to zone 6 for Endless Tower. (bugreport:4707)
+ It's worth noting how much I hate the system for restricting skills per zone.
+ - Fixed Cat Hand warp service warping players to all warp options. (bugreport:4709)
+ - Fixed floor 75 warp in endless tower disabling the wrong warp. (bugreport:4711)
+ - Added a condition for Chungwolmang to only delete items if a certain ID is specified. (bugreport:4719)
+ - Corrected a mobcount specifying the wrong NPC in the Moscovia Ship quest. (bugreport:4736)
2011/01/16
* Rev. 14676 Various fixes for scripts that are disabled by default. [Ai4rei]
- Fixed name collision in Baphomet Jr. taming item quest (custom) with 'Little Boy' in cities/lutie.txt
@@ -20,28 +32,10 @@ Date Added
Airship Ticket Quest, How the Airship Works, Ice Necklace Quest,
Siblings Quest, Thor Volcano Base Quest, Muff's Loan, Broken Diamond,
and the Z-Gang Quest
-2010/11/14
- * Rev. 14462 Updating spawns as a precursor for Eden group quests. [L0ne_W0lf]
- * Updated spawns for Juno fields to Renewal.
- * Updated spawns for Umbala fields to Renewal.
- * Updated spawns for Comodo fields to Renewal
- * Updated spawns for Mjolnir fields to Renewal.
- * Updated spawns for Payon fields to Renewal.
- * Updated spawns for Morroc fields to Renewal.
- * Commented out repeatable EXP quests.
2010/11/04
* Rev. 14448 Just a couple Bug fixes. :P [L0ne_W0lf]
- Added a missing close in quests_13_2.txt. (bugreport:4520)
- Corrected 'IProntera' typo in quests_prontera.txt (bugreport:4522)
-2010/10/23
- * Rev. 14435 Updated spawns for Geffen fields to Renewal. [L0ne_W0lf]
-2010/10/20
- * Rev. 14433 Updated spawns for Prontera fields to Renewal. [L0ne_W0lf]
-2010/10/10
- * Rev. 14422 Wot's dis? Missed a warp in morroc field! THIS WILL NOT DO. [L0ne_W0lf]
- - ...corrected the versions in the file headers as well. :P
- * Rev. 14421 Renewal Update to warp portals, and deleted disabled_warps.txt. [L0ne_W0lf]
- - Only disabled warps, some coordinates might have slipped past me.
2010/09/18
* Rev 14409 Updates, and bugfixes, the usual stuff. [L0ne_W0lf]
* Updated Sage quest skill quest with the file curtosy of 5511.
diff --git a/npc/events/MemorialDay_2008.txt b/npc/events/MemorialDay_2008.txt
index cbecbdae8..9e67216a7 100644
--- a/npc/events/MemorialDay_2008.txt
+++ b/npc/events/MemorialDay_2008.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= Kisuka
//===== Current Version: =====================================
-//= 1.1
+//= 1.2
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -11,6 +11,7 @@
//===== Additional Comments: =================================
//= 1.0 First version. [Kisuka]
//= 1.1 Many Many Fixes. [Kisuka]
+//= 1.2 Some changes. [Kisuka]
//============================================================
// ================== Lauds ======================
@@ -37,16 +38,11 @@ prontera,182,214,4 script Lauds#Memorial 58,{
mes "My what?";
next;
mes "[Mad Sago Lauds]";
- mes "How are you supposed to go on your trip";
- mes "without your towel!?";
+ mes "How are you supposed to go on your trip without your towel!?";
next;
mes "[Mad Sago Lauds]";
- mes "If you think this is just another";
- mes "holiday,";
- mes "I'm not going to waste my breath.";
- mes "But if you like to pay a tribute to";
- mes "great soldiers,";
- mes "I will help you ready yourself";
+ mes "If you think this is just another holiday, I'm not going to waste my breath.";
+ mes "But if you like to pay a tribute to great soldiers, I will help you ready yourself.";
next;
if (select("I guess so...:Are you crazy or something?") == 2) {
mes "[Mad Sago Lauds]";
@@ -62,11 +58,8 @@ prontera,182,214,4 script Lauds#Memorial 58,{
mes "Then listen to me carefully.";
next;
mes "[Mad Sago Lauds]";
- mes "Now before you can pay tribute to";
- mes "the fallen soldiers";
- mes "you must be properly equipped";
- mes "Without your towel you will be";
- mes "lost!";
+ mes "Now before you can pay tribute to the fallen soldiers you must be properly equipped.";
+ mes "Without your towel you will be lost!";
mes "If you bring me the materials, I can make you a towel.";
next;
mes "[Mad Sago Lauds]";
@@ -79,25 +72,19 @@ prontera,182,214,4 script Lauds#Memorial 58,{
else if(Memorial08 == 1) {
if (countitem(1059) < 30 || countitem(914) < 20) {
mes "[Mad Sago Lauds]";
- mes "What are these? They aren't";
- mes "enough?!";
- mes "*Sigh* Do I really have to tell you";
- mes "again?!";
+ mes "What are these? They aren't enough?!";
+ mes "*Sigh* Do I really have to tell you again?!";
mes "Bring me ^FF000030 Fabric and 20 Fluffs^000000.";
close;
}else{
- mes "***Mad Sago Lauds appears to be";
- mes "muttering to himself***";
+ mes "***Mad Sago Lauds appears to be muttering to himself***";
next;
mes "[Mad Sago Lauds]";
- mes "So, did you bring the towel";
- mes "materials?";
+ mes "So, did you bring the towel materials?";
next;
mes "[Mad Sago Lauds]";
- mes "Excellent; you've brought them";
- mes "all.";
- mes "Then I shall make you a Towel of";
- mes "Memory as I promised.";
+ mes "Excellent; you've brought them all.";
+ mes "Then I shall make you a Towel of Memory as I promised.";
mes "Give me a moment.";
next;
mes "[Mad Sago Lauds]";
@@ -113,40 +100,30 @@ prontera,182,214,4 script Lauds#Memorial 58,{
else if(Memorial08 == 2) {
mes "[Mad Sago Lauds]";
- mes "Ah, you have fluffy new towel now";
- mes "I even put your name on it";
+ mes "Ah, you have fluffy new towel now I even put your name on it";
next;
mes "[Mad Sago Lauds]";
- mes "Say, how do you like to go";
- mes "on a journey to pay a tribute to";
- mes "Memorial Day?";
+ mes "Say, how do you like to go on a journey to pay a tribute to Memorial Day?";
next;
if (select("Sure.:No, I'm Busy.") == 2) {
mes "[Mad Sago Lauds]";
- mes "Don't come crying to me";
- mes "if someone decides to";
- mes "build a highway through";
- mes "your home!";
+ mes "Don't come crying to me if someone decides to build a highway through your home!";
close;
}
mes "[Mad Sago Lauds]";
- mes "Good. By the way, do you even know";
- mes "what the towel is for?";
+ mes "Good. By the way, do you even know what the towel is for?";
next;
mes "[Mad Sago Lauds]";
- mes "It seems you're just carrying it";
- mes "without understanding its meaning.";
- mes "What a shame! You should go speak";
- mes "to ^FF0000Grast in Prontera^000000.";
+ mes "It seems you're just carrying it without understanding its meaning.";
+ mes "What a shame! You should go speak to ^FF0000Grast in Prontera^000000.";
set Memorial08,3;
close;
}
else if(Memorial08 == 3) {
mes "[Mad Sago Lauds]";
- mes "What are you still doing here? I";
- mes "told you to go speak to Grast in";
- mes "Prontera!";
+ mes "What are you still doing here?";
+ mes "I told you to go speak to Grast in Prontera!";
close;
}
@@ -163,20 +140,16 @@ prontera,182,214,4 script Lauds#Memorial 58,{
mes "HAHAHAHAHAHA!!!! cough cough";
next;
mes "[Mad Sago Lauds]";
- mes "Please give them to me. Thank you";
- mes "for your hard work, by the way.";
+ mes "Please give them to me. Thank you for your hard work, by the way.";
mes "Say, have you learned anything from the journey?";
- mes "Now is to go visit the plaque at 12";
- mes "o'clock direction in Prontera.";
+ mes "Now is to go visit the plaque at 12 o'clock direction in Prontera.";
next;
mes "[Mad Sago Lauds]";
- mes "What do you mean you were just";
- mes "there?";
+ mes "What do you mean you were just there?";
next;
mes "[Mad Sago Lauds]";
- mes "What? Why are you giving me your";
- mes "garbage!";
- mes "Those items are not useful to me at all";
+ mes "What? Why are you giving me your garbage!";
+ mes "Those items are not useful to me at all.";
mes "You should be going to the plaque!";
set Memorial08,8;
close;
@@ -185,8 +158,7 @@ prontera,182,214,4 script Lauds#Memorial 58,{
else if(Memorial08 == 8) {
mes "[Mad Sago Lauds]";
mes "Stop trying to give me your garbage!";
- mes "Go to the plaque at 12 o'clock";
- mes "direction in Prontera for your journey!";
+ mes "Go to the plaque at 12 o'clock direction in Prontera for your journey!";
close;
}
@@ -201,17 +173,12 @@ prontera,182,214,4 script Lauds#Memorial 58,{
else if(.@RandomMsg == 2) {
mes "[Mad Sago Lauds]";
mes "Life... is like a grapefruit.";
- mes "It's orange and squishy, and has a";
- mes "few pips in it,";
- mes "and some folks have half a one for";
- mes "breakfast.";
+ mes "It's orange and squishy, and has a few pips in it, and some folks have half a one for breakfast.";
close;
}
else if(.@RandomMsg == 3) {
mes "[Mad Sago Lauds]";
- mes "There was a point to this story,";
- mes "but it has temporarily escaped the";
- mes "chronicler's mind.";
+ mes "There was a point to this story, but it has temporarily escaped the chronicler's mind.";
close;
}
else if(.@RandomMsg == 4) {
@@ -221,9 +188,7 @@ prontera,182,214,4 script Lauds#Memorial 58,{
}
else if(.@RandomMsg == 5) {
mes "[Mad Sago Lauds]";
- mes "It is a mistake to think you can";
- mes "solve any major problems just with";
- mes "potatoes.";
+ mes "It is a mistake to think you can solve any major problems just with potatoes.";
close;
}
}
@@ -254,14 +219,11 @@ prontera,153,286,4 script Memorial Plaque#Memorial 857,{
}
L_CleanPlaque:
- mes "- You see a message from the cleaned plaque.";
+ mes "- You see a message from the cleaned plaque.-";
next;
- mes "-Although no sculptured marble";
- mes "should rise to their memory,-";
- mes "-nor engraved stone bear record of";
- mes "their deeds,-";
- mes "-yet will their remembrance be as";
- mes "lasting as the land they honored.-";
+ mes "-Although no sculptured marble should rise to their memory,-";
+ mes "-nor engraved stone bear record of their deeds,-";
+ mes "-yet will their remembrance be as lasting as the land they honored.-";
mes "-Daniel Webster-";
if(Memorial08 == 9) {
getexp 93750,43750;
@@ -269,10 +231,8 @@ prontera,153,286,4 script Memorial Plaque#Memorial 857,{
next;
mes "-There's another message.-";
next;
- mes "-I may not have gone where I";
- mes "intended to go,-";
- mes "-but I think I have ended up where";
- mes "I needed to be.-";
+ mes "-I may not have gone where I intended to go,-";
+ mes "-but I think I have ended up where I needed to be.-";
mes "- Douglas Adams.-";
if(Memorial08 == 9) {
getexp 93750,43750;
@@ -280,12 +240,9 @@ prontera,153,286,4 script Memorial Plaque#Memorial 857,{
next;
mes "-This is the last message.-";
next;
- mes "-True heroism is remarkably sober,";
- mes "very undramatic.-";
- mes "-It is not the urge to surpass all";
- mes "others at whatever cost,-";
- mes "- but the urge to serve others at";
- mes "whatever cost. -";
+ mes "-True heroism is remarkably sober, very undramatic.-";
+ mes "-It is not the urge to surpass all others at whatever cost,-";
+ mes "- but the urge to serve others at whatever cost. -";
mes "- Arthur Ashe -";
if(Memorial08 == 9) {
getexp 93750,43750;
@@ -300,33 +257,24 @@ prontera,153,286,4 script Memorial Plaque#Memorial 857,{
prontera,150,270,4 script Grast#Memorial 900,{
if(Memorial08 < 3) {
mes "[Grast]";
- mes "Memorial Day is a sad and yet";
- mes "glorious day.";
- mes "I wonder how many people remember";
- mes "them...";
+ mes "Memorial Day is a sad and yet glorious day.";
+ mes "I wonder how many people remember them...";
close;
}
else if(Memorial08 == 3) {
mes "[Grast]";
mes "Oh, isn't that a Towel of Memory?";
- mes "I'm so glad to meet someone who";
- mes "understands the meaning of Memorial Day.";
+ mes "I'm so glad to meet someone who understands the meaning of Memorial Day.";
next;
mes "[Grast]";
- mes "It is very important to know what";
- mes "we're celebrating today, don't you think?";
+ mes "It is very important to know what we're celebrating today, don't you think?";
next;
mes "[Grast]";
- mes "If you like to go on a journey to";
- mes "pay a tribute to Memorial Day,";
- mes "you should bring me some materials";
- mes "I ask.";
+ mes "If you like to go on a journey to pay a tribute to Memorial Day, you should bring me some materials I ask.";
next;
mes "[Grast]";
- mes "Please bring me ^FF0000one of each Red";
- mes "Potion, Green Potion, Awakening";
- mes "Potion, and Butterfly Wing^000000.";
+ mes "Please bring me ^FF0000one of each Red Potion, Green Potion, Awakening Potion, and Butterfly Wing^000000.";
mes "I'll be waiting for your return.";
set Memorial08,4;
close;
@@ -335,20 +283,14 @@ prontera,150,270,4 script Grast#Memorial 900,{
else if(Memorial08 == 4) {
if (countitem(501) < 1 || countitem(506) < 1 || countitem(656) < 1 || countitem(602) < 1) {
mes "[Grast]";
- mes "Oops, you haven't brought all";
- mes "materials.";
+ mes "Oops, you haven't brought all materials.";
mes "Please make sure you need to bring me";
- mes " ^FF0000one of each Red Potion, Green";
- mes "Potion, Awakening Potion, and";
- mes "Butteryfly Wing^000000.";
+ mes "^FF0000one of each Red Potion, Green Potion, Awakening Potion, and Butteryfly Wing^000000.";
next;
mes "[Grast]";
- mes "You'll have to bring me more";
- mes "materials afterwards.";
- mes "If you feel too burdened to gather";
- mes "them all,";
- mes "I can provide you all the";
- mes "materials.";
+ mes "You'll have to bring me more materials afterwards.";
+ mes "If you feel too burdened to gather them all,";
+ mes "I can provide you all the materials.";
next;
if (select("I'll gather the rest.:Give me the materials.") == 2) {
goto L_GiveUp;
@@ -362,9 +304,7 @@ prontera,150,270,4 script Grast#Memorial 900,{
mes "Hmm, you will need some more things still...";
next;
mes "[Grast]";
- mes "Please bring me ^FF0000one of each Trap,";
- mes "Yggdrasil Leaf, Blue Gemstone,";
- mes "Crystal Mirror, Meat, and Carrot.^000000";
+ mes "Please bring me ^FF0000one of each Trap, Yggdrasil Leaf, Blue Gemstone, Crystal Mirror, Meat, and Carrot.^000000";
mes "I'll be waiting for your return.";
set Memorial08,5;
close;
@@ -376,15 +316,11 @@ prontera,150,270,4 script Grast#Memorial 900,{
mes "[Grast]";
mes "Oops, you haven't brought all materials.";
mes "Please make sure you'll have to bring me";
- mes " ^FF0000one of each Trap, Yggdrasil Leaf,";
- mes "Blue Gemstone, Crystal Mirror,";
- mes "Meat, and Carrot^000000.";
+ mes "^FF0000one of each Trap, Yggdrasil Leaf, Blue Gemstone, Crystal Mirror, Meat, and Carrot^000000.";
next;
mes "[Grast]";
- mes "You'll have to bring me more";
- mes "materials afterwards.";
- mes "If you feel too burdened to gather them all,";
- mes "I can provide you all the materials.";
+ mes "You'll have to bring me more materials afterwards.";
+ mes "If you feel too burdened to gather them all, I can provide you all the materials.";
next;
if (select("I'll gather the rest.:Give me the materials.") == 2) {
goto L_GiveUp;
@@ -396,9 +332,7 @@ prontera,150,270,4 script Grast#Memorial 900,{
mes "Hmm, I think you need just a little bit more.";
next;
mes "[Grast]";
- mes "Please bring me ^FF0000one of each Pet";
- mes "Incubator, Firecracker, Poring";
- mes "Doll, and Bouquet^000000.";
+ mes "Please bring me ^FF0000one of each Pet Incubator, Firecracker, Poring Doll, and Bouquet^000000.";
set Memorial08,6;
close;
}
@@ -409,17 +343,14 @@ prontera,150,270,4 script Grast#Memorial 900,{
mes "[Grast]";
mes "Oops, you haven't brought all materials.";
mes "Please make sure you need to bring me";
- mes " ^FF0000one of each Pet Incubator,";
- mes "Firecracker, Poring Doll and Bouquet";
+ mes "^FF0000one of each Pet Incubator, Firecracker, Poring Doll and Bouquet";
next;
mes "[Grast]";
mes "They are the last batch of materials.";
- mes "If you feel too burdened to gather them all,";
- mes "I can provide you all the materials.";
+ mes "If you feel too burdened to gather them all, I can provide you all the materials.";
next;
mes "[Grast]";
- mes "If I provide you all materials, however,";
- mes "I won't have to thank you for your service.";
+ mes "If I provide you all materials, however, I won't have to thank you for your service.";
mes "It's your call, " + strcharinfo(0) + ".";
next;
if (select("I'll gather the rest.:Give me the materials.") == 2) {
@@ -429,19 +360,15 @@ prontera,150,270,4 script Grast#Memorial 900,{
}else{
mes "[Grast]";
mes "Have you brought the materials I asked?";
- mes "Ah, thank you for your hard work;";
- mes "you've brought all of them.";
+ mes "Ah, thank you for your hard work you've brought all of them.";
next;
mes "[Grast]";
- mes "I hope you'll learn a valuable";
- mes "lesson while gathering these materials.";
+ mes "I hope you'll learn a valuable lesson while gathering these materials.";
mes "I like to give you a small gift for your service.";
next;
mes "[Grast]";
- mes "You see, I have two different gifts";
- mes "in my each hand.";
- mes "A best thing would be giving you";
- mes "both of them, but...";
+ mes "You see, I have two different gifts in my each hand.";
+ mes "A best thing would be giving you both of them, but...";
mes "How do you like to test your luck, " + strcharinfo(0) + "?";
next;
mes "[Grast]";
@@ -451,8 +378,7 @@ prontera,150,270,4 script Grast#Memorial 900,{
mes "[Grast]";
mes "You've selected my right hand.";
mes "Here's the gift for you.";
- mes "Now, please bring all these";
- mes "materials to Lauds.";
+ mes "Now, please bring all these materials to Lauds.";
set Memorial08, 7;
getitem 617,1;
close;
@@ -460,8 +386,7 @@ prontera,150,270,4 script Grast#Memorial 900,{
mes "[Grast]";
mes "You've selected my left hand.";
mes "Here's the gift for you.";
- mes "Now, please bring all these";
- mes "materials to Lauds.";
+ mes "Now, please bring all these materials to Lauds.";
set Memorial08, 7;
getitem 12109,1;
close;
@@ -471,43 +396,32 @@ prontera,150,270,4 script Grast#Memorial 900,{
else if(Memorial08 == 7) {
mes "[Grast]";
mes "Have you met Lauds?";
- mes "I hope you'll remember your freedom";
- mes "and happiness";
- mes "are built on thousands of lives";
- mes "sacrificed in war.";
+ mes "I hope you'll remember your freedom and happiness are built on thousands of lives sacrificed in war.";
close;
}
else if(Memorial08 >= 8) {
mes "[Grast]";
- mes "A towel is about the most massively";
- mes "useful thing an adventurer can have.";
+ mes "A towel is about the most massively useful thing an adventurer can have.";
close;
}
L_GiveUp:
mes "[Grast]";
- mes "Oh, I see. I guess you're quite";
- mes "busy nowadays, huh?";
- mes "No problem; I'll give you all the";
- mes "supplies...";
+ mes "Oh, I see. I guess you're quite busy nowadays, huh?";
+ mes "No problem; I'll give you all the supplies...";
next;
mes "[Grast]";
mes "There you go.";
- mes "I crushed all the items together";
- mes "into a more compact form for you";
- mes "You can thank me later for that";
- mes "extra service.";
+ mes "I crushed all the items together into a more compact form for you.";
+ mes "You can thank me later for that extra service.";
mes "Please bring them to Lauds.";
set Memorial08,7;
getitem 7126,1;
next;
mes "[Grast]";
- mes "By the way, he had an unfortunate";
- mes "accident, and has kind of lost his";
- mes "mind.";
- mes "Please don't be alarmed even if he";
- mes "starts babbling.";
+ mes "By the way, he had an unfortunate accident, and has kind of lost his mind.";
+ mes "Please don't be alarmed even if he starts babbling.";
close;
L_Continue:
diff --git a/npc/events/StPatrick_2008.txt b/npc/events/StPatrick_2008.txt
index eeaa49dd9..8fac11831 100644
--- a/npc/events/StPatrick_2008.txt
+++ b/npc/events/StPatrick_2008.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= Kisuka
//===== Current Version: =====================================
-//= 1.4
+//= 1.5
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -29,6 +29,7 @@
//= Corrected EXP rewards, and some typos.
//= 1.3 Corrected random in item function. [L0ne_W0lf]
//= 1.4 Replaced effect numerics with constants. [Samuray22]
+//= 1.5 Revamped the script. [Kisuka]
//============================================================
prt_fild05,170,286,4 script Anxious Leprechaun#8pday 954,{
@@ -37,159 +38,105 @@ prt_fild05,170,286,4 script Anxious Leprechaun#8pday 954,{
mes "Hmm...";
mes "Tis a fine day it be.";
mes "If you have a moment to spare.";
- mes "Come here to me now,";
- mes "come here and I'll tell ya something.";
+ mes "Come here to me now, come here and I'll tell ya something.";
next;
select("Go ahead.");
mes "[O'Riley the Leprechaun]";
- mes "These past years I've";
- mes "come to see the world";
- mes "and each time the snakes";
- mes "have stolen me treasure.";
+ mes "These past years I've come to see the world and each time the snakes have stolen me treasure.";
next;
select("Oh?");
mes "[O'Riley the Leprechaun]";
- mes "Ye fine folks of this land";
- mes "have been so gracious";
- mes "to recover me treasure again and again.";
+ mes "Ye fine folks of this land have been so gracious to recover me treasure again and again.";
next;
mes "[O'Riley the Leprechaun]";
- mes "I've learned me lesson";
- mes "and will never forget how those";
- mes "vile snakes have wronged me.";
+ mes "I've learned me lesson and will never forget how those vile snakes have wronged me.";
next;
select("What did you do?");
mes "[O'Riley the Leprechaun]";
- mes "I made a safe place to hide me";
- mes "treasure.";
- mes "Hidden in a secret place the treasure";
- mes "would be safe until I returned";
- mes "to the world the following year.";
+ mes "I made a safe place to hide me treasure.";
+ mes "Hidden in a secret place the treasure would be safe until I returned to the world the following year.";
next;
mes "[O'Riley the Leprechaun]";
- mes "This year, I have made me journey";
- mes "to see the outside world once again.";
- mes "I traveled to me cache of gold";
- mes "I found it to be safe and";
- mes "undisturbed.";
+ mes "This year, I have made me journey to see the outside world once again.";
+ mes "I traveled to me cache of gold I found it to be safe and undisturbed.";
next;
mes "[O'Riley the Leprechaun]";
- mes "I thought to meself,";
- mes "I am very clever to hide the";
- mes "treasure from the snakes.";
+ mes "I thought to meself, I am very clever to hide the treasure from the snakes.";
mes "Oh, but I was a fool still.";
next;
select("What happened?");
mes "[O'Riley the Leprechaun]";
mes "My hiding place was too clever.";
- mes "I pulled and I heaved and pushed,";
- mes "but the hiding place would not";
- mes "budge.";
- mes "So once again, I am without";
- mes "treasure this year.";
+ mes "I pulled and I heaved and pushed, but the hiding place would not budge.";
+ mes "So once again, I am without treasure this year.";
next;
mes "[O'Riley the Leprechaun]";
- mes "I have not even begun brewing";
- mes "me famous green ale on account of";
- mes "this mess.";
- mes "I will ask ye, will ya help get me";
- mes "treasure back?";
+ mes "I have not even begun brewing me famous green ale on account of this mess.";
+ mes "I will ask ye, will ya help get me treasure back?";
next;
if (select("Sure, I can help you.:I'm too busy.") == 2) {
mes "[O'Riley the Leprechaun]";
mes "Aye, I understand.";
- mes "Thank you for listening to me";
- mes "tale.";
+ mes "Thank you for listening to me tale.";
close;
}
mes "[O'Riley the Leprechaun]";
mes "To find my treasure it be true.";
- mes "To my treasure I give my secret to";
- mes "you.";
+ mes "To my treasure I give my secret to you.";
next;
mes "[O'Riley the Leprechaun]";
- mes "So, listen well and make no";
- mes "omissions.";
- mes "Make the journey to the city of";
- mes "magicians.";
- mes "Over the bridge and across the";
- mes "water";
- mes "Climb the mountain until north ye";
- mes "can travel no farther.";
+ mes "So, listen well and make no omissions.";
+ mes "Make the journey to the city of magicians.";
+ mes "Over the bridge and across the water";
+ mes "Climb the mountain until north ye can travel no farther.";
next;
mes "[O'Riley the Leprechaun]";
- mes "Passed the stone steps set into the";
- mes "air.";
- mes "Hidden in the mountain side,";
- mes "me treasure is there.";
+ mes "Passed the stone steps set into the air.";
+ mes "Hidden in the mountain side, me treasure is there.";
next;
mes "[O'Riley the Leprechaun]";
- mes "Ye must find a way to break it";
- mes "open.";
- mes "Ye will need a mighty explosion";
- mes "to free the cache to be sure.";
+ mes "Ye must find a way to break it open.";
+ mes "Ye will need a mighty explosion to free the cache to be sure.";
next;
mes "[O'Riley the Leprechaun]";
mes "Ye might try some Firecrackers.";
- mes "Course, Ye would need a great";
- mes "number of them,";
- mes "Ye would need at least ^FF0000200";
- mes "Firecreackers^000000";
+ mes "Course, Ye would need a great number of them, Ye would need at least ^FF0000200 Firecreackers^000000";
set StPatrick2008,1;
close;
}
else if (StPatrick2008 == 1) {
mes "[O'Riley the Leprechaun]";
mes "Tis a fine day it be.";
- mes "Have you found me treasure yet,";
- mes "have you?";
- mes "Me hiding spot is a might hard to";
- mes "crack.";
+ mes "Have you found me treasure yet, have you?";
+ mes "Me hiding spot is a might hard to crack.";
next;
mes "[O'Riley the Leprechaun]";
mes "Ye might try some Firecrackers.";
- mes "Course, Ye would need a great";
- mes "number of them,";
- mes "Ye would need at least ^FF0000200";
- mes "Firecreackers^000000";
+ mes "Course, Ye would need a great number of them, Ye would need at least ^FF0000200 Firecreackers^000000";
next;
mes "[O'Riley the Leprechaun]";
- mes "I be understanding if you can't get";
- mes "to it";
- mes "to be sure to be sure.";
+ mes "I be understanding if you can't get to it to be sure to be sure.";
close;
}
else if (StPatrick2008 == 2) {
mes "[O'Riley the Leprechaun]";
mes "Oh, welcome back!";
- mes "Thank you for returning me";
- mes "treasure!";
+ mes "Thank you for returning me treasure!";
mes "Me gratitude knows no bounds!";
next;
mes "[O'Riley the Leprechaun]";
mes "I am so happy,";
- mes "I'll be starting up me brew right";
- mes "away";
+ mes "I'll be starting up me brew right away";
next;
mes "[O'Riley the Leprechaun]";
- mes "It seems that the snakes have";
- mes "returned this year";
- mes "and are here to steal my treasure";
- mes "again.";
+ mes "It seems that the snakes have returned this year and are here to steal my treasure again.";
next;
mes "[O'Riley the Leprechaun]";
- mes "The snakes carry the coins";
- mes "of my kinsmen and must be";
- mes "punished.";
- mes "But ye have had a long journey, for";
- mes "which I am";
- mes "very grateful.";
+ mes "The snakes carry the coins of my kinsmen and must be punished.";
+ mes "But ye have had a long journey, for which I am very grateful.";
next;
mes "[O'Riley the Leprechaun]";
- mes "When ye have had a moment to rest";
- mes "ye legs,";
- mes "come talk to me again and we may";
- mes "speak again";
+ mes "When ye have had a moment to rest ye legs, come talk to me again and we may speak again";
close2;
set StPatrick2008,3;
getexp 200000,70000;
@@ -202,39 +149,23 @@ prt_fild05,170,286,4 script Anxious Leprechaun#8pday 954,{
next;
mes "[O'Riley the Leprechaun]";
mes "Thank you for coming by again.";
- mes "The snakes carry the coins of my";
- mes "kindsmen";
- mes "and must be punished.";
+ mes "The snakes carry the coins of my kindsmen and must be punished.";
next;
mes "[O'Riley the Leprechaun]";
- mes "I would be so generous to give you";
- mes "some of my famous brew";
- mes "if you would bring me the";
- mes "ill-gotten gains carried";
- mes "by those vile snakes";
+ mes "I would be so generous to give you some of my famous brew if you would bring me the ill-gotten gains carried by those vile snakes";
next;
- mes "And if you find one of the";
- mes "treasures of my kin";
- mes "please bring me those coins";
- mes "so that the snakes don't get them.";
+ mes "And if you find one of the treasures of my kin please bring me those coins so that the snakes don't get them.";
set StPatrick2008,4;
close;
}
else if (StPatrick2008 == 4) {
mes "[O'Riley the Leprechaun]";
- mes "The snakes carry too many of me";
- mes "kinsmen's coin";
- mes "I be passing out pints of me brew";
- mes "as reward for their return.";
+ mes "The snakes carry too many of me kinsmen's coin I be passing out pints of me brew as reward for their return.";
next;
mes "[O'Riley the Leprechaun]";
- mes "I'll reward ye with one jug of ale";
- mes "for ^0000FF1 Golden Coins^000000, ^0000FF5 Silver Coins^000000,";
- mes "or ^0000FF10 Bronze Coins^000000.";
- mes "It be a fair bounty for the";
- mes "ill-gotten coins.";
- mes "So, what kind of coin have ye";
- mes "brought?";
+ mes "I'll reward ye with one jug of ale for ^0000FF1 Golden Coins^000000, ^0000FF5 Silver Coins^000000, or ^0000FF10 Bronze Coins^000000.";
+ mes "It be a fair bounty for the ill-gotten coins.";
+ mes "So, what kind of coin have ye brought?";
next;
switch(select("Bronze Coins:Silver Coins:Gold Coins:Quit.")) {
case 1:
@@ -263,9 +194,7 @@ prt_fild05,170,286,4 script Anxious Leprechaun#8pday 954,{
close;
case 4:
mes "[O'Riley the Leprechaun]";
- mes "I'll reward ye with one jug of ale";
- mes "for ^0000FF1 Golden Coins^000000, ^0000FF5 Silver Coins^000000,";
- mes "or ^0000FF10 Bronze Coins^000000.";
+ mes "I'll reward ye with one jug of ale for ^0000FF1 Golden Coins^000000, ^0000FF5 Silver Coins^000000, or ^0000FF10 Bronze Coins^000000.";
close;
}
}
@@ -276,37 +205,30 @@ mjolnir_01,272,363,4 script Rocks#08StPattysDay -1,1,1,{
OnTouch:
if (StPatrick2008 < 1) {
- mes "- You've found a pile of rocks";
- mes "covered with soil. -";
+ mes "- You've found a pile of rocks covered with soil. -";
close;
}
if (StPatrick2008 == 1) {
- mes "- You've found a pile of rocks";
- mes "covered with soil. -";
+ mes "- You've found a pile of rocks covered with soil. -";
next;
if (countitem(12018) < 200) {
mes "The rocks won't budge.";
- mes "Maybe O'Riley knows a way to move";
- mes "the rocks.";
+ mes "Maybe O'Riley knows a way to move the rocks.";
close;
}
else {
if (select("Use Firecrackers.:Ignore") == 2) {
close;
}
- mes "You buried 200 Firecrackers";
- mes "under the pile of rocks.";
+ mes "You buried 200 Firecrackers under the pile of rocks.";
mes "You light the fuse.";
next;
mes "*BOOM!*";
specialeffect2 EF_LORD;
next;
- mes "After A cloud of dust and smoke has";
- mes "dissipated,";
- mes "You've found a box between the";
- mes "rocks and soil.";
- mes "This box must contain O'Riley's";
- mes "valuables.";
+ mes "After A cloud of dust and smoke has dissipated,";
+ mes "You've found a box between the rocks and soil.";
+ mes "This box must contain O'Riley's valuables.";
mes "Let's bring the box to O'Riley.";
close2;
set StPatrick2008,2;
diff --git a/npc/events/christmas_2008.txt b/npc/events/christmas_2008.txt
index 99b783a22..a696de501 100644
--- a/npc/events/christmas_2008.txt
+++ b/npc/events/christmas_2008.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= Kisuka
//===== Current Version: =====================================
-//= 1.0
+//= 1.1
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -15,33 +15,31 @@
//= Must enable X-mas08 mobs in mob_db2.
//===== Additional Comments: =================================
//= 1.0 First version. [Kisuka]
+//= 1.1 Fixed some issues, revamped the whole script. [Kisuka]
//============================================================
-// ============== Carolling - Music Box ================
+// ============== Caroller - Music Box ================
// =====================================================
-prontera,226,306,4 script Carolling#iROxmas08 79,{
+prontera,226,306,4 script Caroller#iROxmas08 79,{
if (iROxmas08carol < 1 || iROxmas08carol == 3) {
if (iROxmas08carol == 3) {
- mes "[Carolling]";
- mes "Jingle Bells! Jingle Bells! Jingle";
- mes "all the way!";
- mes "O' what fun it is to ride in a";
- mes "one-horse open sleeeigh, Hey!";
+ mes "[Caroller]";
+ mes "Jingle Bells! Jingle Bells! Jingle all the way!";
+ mes "O' what fun it is to ride in a one-horse open sleeeigh, Hey!";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Merry Christmas!";
- mes "Hey! You! What comes to mind when";
- mes "you think about Christmas?";
+ mes "Hey! You! What comes to mind when you think about Christmas?";
next;
}else{
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Jingle Bells! Jingle Bells! Jingle all the way!";
next;
- specialeffect 75;
- mes "[Carolling]";
+ specialeffect EF_GLORIA;
+ mes "[Caroller]";
mes "O' what fun it is to ride in a one-horse open sleigh!";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Merry Christmas!";
if (Sex) {
mes "Hey, boy! What comes to mind when";
@@ -54,291 +52,229 @@ prontera,226,306,4 script Carolling#iROxmas08 79,{
switch(select("Santa Claus:Gift Boxes:Carols:Santa Costumes:Fake Santa Antonio")) {
case 1:
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Santa Claus!";
mes "You're so innocent!!";
mes "Ah!";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Here's a secret!";
- mes "There's a rumor that Santa Claus";
- mes "lives in a certain village all";
- mes "throughout the year.";
+ mes "There's a rumor that Santa Claus lives in a certain village all throughout the year.";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "But now!!!";
mes "In this Christmas season!!";
- mes "You guys can meet Santa on either";
- mes "of the five possible villages";
- mes "throughout Rune-Midgerts!";
+ mes "You guys can meet Santa on either of the five possible villages throughout Rune-Midgerts!";
next;
- mes "[Carolling]";
- mes "If you win over Santa, you can get";
- mes "a gift. Would you go for it?";
+ mes "[Caroller]";
+ mes "If you win over Santa, you can get a gift. Would you go for it?";
next;
emotion 18;
- mes "[Carolling]";
- mes "Carolling's hot news! Ha!";
+ mes "[Caroller]";
+ mes "Caroller's hot news! Ha!";
mes "Isn't that big news?";
close;
case 2:
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Gift boxes?! All right!";
- mes "Isn't it thrilling to open gifts";
- mes "over your head!!";
+ mes "Isn't it thrilling to open gifts over your head!!";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Anyway, did you know...";
- mes "Some villain, a fake Santa robbed";
- mes "some gifts from the good Santa!";
+ mes "Some villain, a fake Santa robbed some gifts from the good Santa!";
next;
- mes "[Carolling]";
- mes "Furthermore, he has put bad magic";
- mes "on the gifts so that they become";
- mes "monsters!";
+ mes "[Caroller]";
+ mes "Furthermore, he has put bad magic on the gifts so that they become monsters!";
next;
emotion 18;
- mes "[Carolling]";
- mes "Carolling's hot news! Ha!";
+ mes "[Caroller]";
+ mes "Caroller's hot news! Ha!";
mes "Isn't it amazing?";
close;
case 3:
if (iROxmas08carol == 3) {
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Ah, a music box is useful.";
next;
- mes "[Carolling]";
- mes "Though we can't all play it around";
- mes "the village as we planned, it's";
- mes "cool that you carry it.";
+ mes "[Caroller]";
+ mes "Though we can't all play it around the village as we planned, it's cool that you carry it.";
next;
- mes "[Carolling]";
- mes "We want to enjoy carols all";
- mes "together... I hope to get Crystal";
- mes "Pieces!";
+ mes "[Caroller]";
+ mes "We want to enjoy carols all together... I hope to get Crystal Pieces!";
next;
- mes "[Carolling]";
- mes "If you can get ^0000FFSinging Crystal";
- mes "Pieces^000000, give them to me please?";
+ mes "[Caroller]";
+ mes "If you can get ^0000FFSinging Crystal Pieces^000000, give them to me please?";
next;
select("Why not? Sure, I can give you some.");
if (countitem(6092) < 6) {
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Yes, please.";
next;
- mes "[Carolling]";
- mes "If you can get ^0000FFSinging Crystal";
- mes "Pieces^000000, give them to me please?";
+ mes "[Caroller]";
+ mes "If you can get ^0000FFSinging Crystal Pieces^000000, give them to me please?";
close;
}else{
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Wow, you have them.";
next;
- mes "[Carolling]";
- mes "I can bake you a cake,";
- mes "and I can carve your name on the";
- mes "cake, if you want!";
+ mes "[Caroller]";
+ mes "I can bake you a cake, and I can carve your name on the cake, if you want!";
next;
if (select("No, thanks.:Please name it for me.") == 2) {
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Thank for your help!";
next;
- mes "[Carolling]";
- mes "Many people live in the giant";
- mes "world!";
- mes "So many people hope to hear";
- mes "carolling, yet I always lack";
- mes "Crystal pieces.";
+ mes "[Caroller]";
+ mes "Many people live in the giant world!";
+ mes "So many people hope to hear Caroller, yet I always lack Crystal pieces.";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "If you can get ^0000FFSinging Crystal Pieces^000000, give them to me please?";
next;
emotion 18;
delitem 6092,6;
getnameditem 12354,"+strcharinfo(0)+";
- mes "[Carolling]";
- mes "Let's care about others around you";
- mes "on this Christmas season!";
+ mes "[Caroller]";
+ mes "Let's care about others around you on this Christmas season!";
close;
}else{
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Oh!";
mes "Shyness!";
next;
- mes "[Carolling]";
- mes "Anyway, thanks a lot for your";
- mes "help.";
+ mes "[Caroller]";
+ mes "Anyway, thanks a lot for your help.";
next;
- mes "[Carolling]";
- mes "Many people live in the giant";
- mes "world!";
- mes "So many people hope to hear";
- mes "carolling, yet I always lack";
- mes "Crystal pieces.";
+ mes "[Caroller]";
+ mes "Many people live in the giant world!";
+ mes "So many people hope to hear Caroller, yet I always lack Crystal pieces.";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "If you can get ^0000FFSinging Crystal Pieces^000000, give them to me please?";
next;
emotion 18;
delitem 6092,6;
getitem 12354,1;
- mes "[Carolling]";
- mes "Let's care about others around you";
- mes "on this Christmas season!";
+ mes "[Caroller]";
+ mes "Let's care about others around you on this Christmas season!";
close;
}
}
}
- mes "[Carolling]";
+ mes "[Caroller]";
mes "You know about Christmas!";
mes "Talking about Christmas...";
mes "...it's carols!!!";
mes "I've been waiting for this for when";
mes "Christmas comes around!";
next;
- mes "[Carolling]";
- mes "But there's been no caroling here";
- mes "and there like before, so we can't";
- mes "feel the Christmas spirit.";
+ mes "[Caroller]";
+ mes "But there's been no caroling here and there like before, so we can't feel the Christmas spirit.";
next;
- mes "[Carolling]";
- mes "So, I installed a Singing Crystal";
- mes "in Prontera...";
+ mes "[Caroller]";
+ mes "So, I installed a Singing Crystal in Prontera...";
next;
- mes "[Carolling]";
- mes "but that jerk Antonio broke the";
- mes "crystal!";
+ mes "[Caroller]";
+ mes "but that jerk Antonio broke the crystal!";
next;
- mes "[Carolling]";
- mes "The gift boxes have been changing";
- mes "into monsters since Antonio placed";
- mes "some magic on them, so the monsters";
- mes "ate up the crystal fragments!";
+ mes "[Caroller]";
+ mes "The gift boxes have been changing into monsters since Antonio placed some magic on them, so the monsters ate up the crystal fragments!";
next;
- mes "[Carolling]";
- mes "I am so devastated, since the";
- mes "Singing Crystal has been the hope";
- mes "of many children around the villages.";
+ mes "[Caroller]";
+ mes "I am so devastated, since the Singing Crystal has been the hope of many children around the villages.";
next;
if (select("There's no other way to carol?:You can hear carols in Lutie.") == 2) {
- mes "[Carolling]";
- mes "And just stay there, every";
- mes "Christmas, for your whole life?";
+ mes "[Caroller]";
+ mes "And just stay there, every Christmas, for your whole life?";
next;
mes "["+strcharinfo(0)+"]";
mes "What? What do you mean?";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Oh, nevermind.";
mes "Ah...";
close;
}
- mes "[Carolling]";
- mes "Maybe, it's quite hard to make a";
- mes "jukebox for the villages, but a";
- mes "music box might be possible.";
+ mes "[Caroller]";
+ mes "Maybe, it's quite hard to make a jukebox for the villages, but a music box might be possible.";
next;
- mes "[Carolling]";
- mes "We need the ^0000FFSinging Crystal Pieces^000000";
- mes "that the monsters ate up.";
+ mes "[Caroller]";
+ mes "We need the ^0000FFSinging Crystal Pieces^000000 that the monsters ate up.";
next;
- mes "[Carolling]";
- mes "Please bring me ^0000FF6 Singing Crystal";
- mes "Pieces^000000, and you will be rewarded";
- mes "with presents!";
+ mes "[Caroller]";
+ mes "Please bring me ^0000FF6 Singing Crystal Pieces^000000, and you will be rewarded with presents!";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Sounds cool, huh!!";
next;
select("........................");
- mes "[Carolling]";
- mes "...Why are you staring at me like";
- mes "that?";
+ mes "[Caroller]";
+ mes "...Why are you staring at me like that?";
next;
- mes "[Carolling]";
- mes "You're thinking that we are always";
- mes "getting our plans spoiled, aren't";
- mes "you?";
+ mes "[Caroller]";
+ mes "You're thinking that we are always getting our plans spoiled, aren't you?";
next;
- mes "[Carolling]";
- mes "I know that we are not good at";
- mes "controlling stuff, but our rewards";
- mes "are good, right?";
+ mes "[Caroller]";
+ mes "I know that we are not good at controlling stuff, but our rewards are good, right?";
next;
select("........................");
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Hey, we treat you good...";
next;
select("........................");
- mes "[Carolling]";
+ mes "[Caroller]";
mes "You are so cruel to me!";
mes "Bad! Bad!";
next;
- mes "[Carolling]";
- mes "Please, for our children's";
- mes "hope!!!?";
- mes "Please bring me 6 Singing Crystal";
- mes "Pieces from ^0000FFViolent Gift Boxes^000000!";
+ mes "[Caroller]";
+ mes "Please, for our children's hope!!!?";
+ mes "Please bring me 6 Singing Crystal Pieces from ^0000FFViolent Gift Boxes^000000!";
next;
emotion 33;
- mes "[Carolling]";
- mes "They're definitely as";
- mes "harsh as their name.";
+ mes "[Caroller]";
+ mes "They're definitely as harsh as their name.";
mes "Go on please!";
set iROxmas08carol,1;
close;
case 4:
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Santa costumes!!";
- mes "You know, the santa costumes that";
- mes "the monsters are wearing now aren't";
- mes "genuine!";
+ mes "You know, the santa costumes that the monsters are wearing now aren't genuine!";
next;
- mes "[Carolling]";
- mes "The rumor 'round here is, Lutie's";
- mes "designer made these costumes.";
+ mes "[Caroller]";
+ mes "The rumor 'round here is, Lutie's designer made these costumes.";
next;
- mes "[Carolling]";
- mes "Every year, adventurers challenge";
- mes "to attack Antonio the fake Santa,";
- mes "but there's no way to catch up to";
- mes "him due to his hat and costume!";
+ mes "[Caroller]";
+ mes "Every year, adventurers challenge to attack Antonio the fake Santa, but there's no way to catch up to him due to his hat and costume!";
next;
- mes "[Carolling]";
- mes "Are there some spcial abilities";
- mes "within them?";
- mes "There's still the designer in the";
- mes "Christmas village... How about";
- mes "asking her to make that costume?";
+ mes "[Caroller]";
+ mes "Are there some spcial abilities within them?";
+ mes "There's still the designer in the Christmas village... How about asking her to make that costume?";
next;
emotion 18;
- mes "[Carolling]";
- mes "Carolling's hot news! Ha!";
+ mes "[Caroller]";
+ mes "Caroller's hot news! Ha!";
mes "It's hot, huh?";
close;
case 5:
- mes "[Carolling]";
+ mes "[Caroller]";
mes "A-N-T-O-N-I-O!!!";
- mes "As I heard, this Antonio is quite";
- mes "different from before.";
+ mes "As I heard, this Antonio is quite different from before.";
next;
- mes "[Carolling]";
- mes "He seems to be quite resolved with";
- mes "himself since he ran away from";
- mes "people before.";
+ mes "[Caroller]";
+ mes "He seems to be quite resolved with himself since he ran away from people before.";
next;
- mes "[Carolling]";
- mes "And he isn't alone anymore... is";
- mes "what I heard...";
+ mes "[Caroller]";
+ mes "And he isn't alone anymore... is what I heard...";
next;
emotion 18;
- mes "[Carolling]";
- mes "Carolling's hot news! Ha!";
+ mes "[Caroller]";
+ mes "Caroller's hot news! Ha!";
mes "Hotness, right?";
close;
}
@@ -346,80 +282,64 @@ prontera,226,306,4 script Carolling#iROxmas08 79,{
if (iROxmas08carol == 1) {
if (countitem(6092) < 6) {
- mes "[Carolling]";
- mes "Maybe, it's quite hard to make a";
- mes "jukebox for the villages, but a";
- mes "music box might be possible.";
+ mes "[Caroller]";
+ mes "Maybe, it's quite hard to make a jukebox for the villages, but a music box might be possible.";
next;
- mes "[Carolling]";
- mes "We need the ^0000FFSinging Crystal Pieces^000000";
- mes "that the monsters ate up.";
+ mes "[Caroller]";
+ mes "We need the ^0000FFSinging Crystal Pieces^000000 that the monsters ate up.";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Please bring me ^0000FF6 Singing Crystal Pieces^000000, and you will be rewarded with presents!";
next;
- mes "[Carolling]";
- mes "For all of the children of this";
- mes "world!!!";
- mes "Please bring me ^0000FFSinging Crystal";
- mes "Pieces^000000 from ^0000FFViolent Gift Boxes^000000!";
+ mes "[Caroller]";
+ mes "For all of the children of this world!!!";
+ mes "Please bring me ^0000FFSinging Crystal Pieces^000000 from ^0000FFViolent Gift Boxes^000000!";
next;
emotion 33;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Be careful!";
- mes "They're definitely as";
- mes "harsh as their name.";
+ mes "They're definitely as harsh as their name.";
mes "Take care!!!";
close;
}else{
- specialeffect 75;
- mes "[Carolling]";
+ specialeffect EF_GLORIA;
+ mes "[Caroller]";
mes "Don't cry, don't cry!";
- mes "Santa won't give you a";
- mes "gift if you're crying.";
+ mes "Santa won't give you a gift if you're crying.";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
select("I got them!");
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Wow, you got them!";
mes "They are so cruel, aren't they?";
mes "I'm happy to see you again.";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Let's count together!";
mes "... ...";
mes "Six!!";
next;
- mes "[Carolling]";
- mes "All right! We can start to make our";
- mes "music box with crystal fragments.";
+ mes "[Caroller]";
+ mes "All right! We can start to make our music box with crystal fragments.";
next;
- mes "[Carolling]";
- mes "We would amplify the sounds of the";
- mes "crystal fragments to sound through";
- mes "the music box.";
+ mes "[Caroller]";
+ mes "We would amplify the sounds of the crystal fragments to sound through the music box.";
next;
- mes "[Carolling]";
- mes "You know, a music box that sounds";
- mes "like a jukebox!";
+ mes "[Caroller]";
+ mes "You know, a music box that sounds like a jukebox!";
next;
- mes "[Carolling]";
- mes "It's handy. You can carry it, as";
- mes "well as listen to sweet carols";
- mes "anywhere. Doesn't that sound";
- mes "cool!?";
+ mes "[Caroller]";
+ mes "It's handy. You can carry it, as well as listen to sweet carols anywhere.";
+ mes "Doesn't that sound cool!?";
next;
- mes "[Carolling]";
- mes "So, we need more of some";
- mes "materials.";
- mes "^0000FF10 Wooden Block, 1 Hammer Of";
- mes "Blacksmith, 1 Jubilee, 10 Sticky";
- mes "Mucus, 3-karat Diamond^000000!";
+ mes "[Caroller]";
+ mes "So, we need more of some materials.";
+ mes "^0000FF10 Trunk, 1 Hammer Of Blacksmith, 1 Jubilee, 10 Sticky Mucus, 3carat Diamond^000000!";
next;
delitem 6092,6;
emotion 33;
set iROxmas08carol,2;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Those are all needed.";
mes "Isn't that easy?";
close;
@@ -428,86 +348,72 @@ prontera,226,306,4 script Carolling#iROxmas08 79,{
if (iROxmas08carol == 2) {
if (countitem(1019) < 10 || countitem(1005) < 1 || countitem(7312) < 1 || countitem(938) < 10 || countitem(732) < 1) {
- mes "[Carolling]";
- mes "We can make a music box";
- mes "with Singing Crystal Pieces.";
- mes "It's handy, you can hear carols";
- mes "anywhere. Sounds cool?";
+ mes "[Caroller]";
+ mes "We can make a music box with Singing Crystal Pieces.";
+ mes "It's handy, you can hear carols anywhere. Sounds cool?";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "So, we need more of some materials.";
- mes "^0000FF10 Wooden Block, 1 Hammer Of";
- mes "Blacksmith, 1 Jubilee, 10 Sticky";
- mes "Mucus, 3-karat Diamond^000000!";
+ mes "^0000FF10 Trunk, 1 Hammer Of Blacksmith, 1 Jubilee, 10 Sticky Mucus, 3carat Diamond^000000!";
next;
emotion 33;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "That's all we need.";
mes "Isn't that easy?";
close;
}else{
- specialeffect 75;
- mes "[Carolling]";
+ specialeffect EF_GLORIA;
+ mes "[Caroller]";
mes "Jingle bells, jingle bells,";
mes "jingle all the way!";
mes "O what fun it is to ride, in a";
mes "one... horse... o-pen... sleigh!!!";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Wow!";
mes "You came back!";
- mes "Did you bring all the";
- mes "materials?";
+ mes "Did you bring all the materials?";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Good!";
- mes "No need to hesitate! Let's get";
- mes "started to make our music box.";
+ mes "No need to hesitate! Let's get started to make our music box.";
next;
- mes "[Carolling]";
- specialeffect 101;
- mes "Blacksmith hammers on wooden";
- mes "block... and we shape the frame.";
+ mes "[Caroller]";
+ specialeffect EF_REPAIRWEAPON;
+ mes "Blacksmith hammers on trunk... and we shape the frame.";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
//(effect - stones from ground?)
- mes "Please use the Singing Crystal";
- mes "Pieces for a column, the Diamond as";
- mes "a prop, and the Sticky Mucus as";
- mes "glue.";
+ mes "Please use the Singing Crystal Pieces for a column, the Diamond as a prop, and the Sticky Mucus as glue.";
next;
- mes "[Carolling]";
- specialeffect 1;
+ mes "[Caroller]";
+ specialeffect EF_HIT2;
mes "And now...";
mes "we decorate with a Jubilee...";
next;
- mes "[Carolling]";
- specialeffect 88;
+ mes "[Caroller]";
+ specialeffect EF_SUFFRAGIUM;
mes "The last step...!";
mes "Breating life into it!";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "It's done now!!!";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "It's so cool! Isn't it cute!!?!";
next;
- mes "[Carolling]";
- mes "You did as I requested, so I will";
- mes "give you gifts, as promised.";
+ mes "[Caroller]";
+ mes "You did as I requested, so I will give you gifts, as promised.";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "One, is this music box.";
- mes "Please play this music box all over";
- mes "the villages!";
+ mes "Please play this music box all over the villages!";
next;
- mes "[Carolling]";
- mes "Another present is a Christmas cake";
- mes "especially shaped like your name!";
- mes "I made this cake shaped like your";
- mes "name!";
+ mes "[Caroller]";
+ mes "Another present is a Christmas cake especially shaped like your name!";
+ mes "I made this cake shaped like your name!";
next;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Don't worry, it tastes good.";
next;
emotion 33;
@@ -519,7 +425,7 @@ prontera,226,306,4 script Carolling#iROxmas08 79,{
delitem 938,10;
delitem 732,1;
set iROxmas08carol,3;
- mes "[Carolling]";
+ mes "[Caroller]";
mes "Thanks a lot.";
mes "Merry Christmas!";
mes "Have a good holiday season!";
@@ -532,22 +438,18 @@ prontera,226,306,4 script Carolling#iROxmas08 79,{
// =====================================================
- script Santa Claus#iROxmas08::08santa 718,{
mes "[Santa Claus]";
- mes "Wow! Were you naughty or nice this";
- mes "year?";
- mes "All right, what comes to your mind";
- mes "when you think about Christmas?";
+ mes "Wow! Were you naughty or nice this year?";
+ mes "All right, what comes to your mind when you think about Christmas?";
next;
switch(select("Carolling:Santa Claus:Gift Boxes:Santa Costume:Not much really...")) {
case 1:
mes "[Santa Claus]";
mes "Carolling! That's good!";
- mes "A sweet carol always makes";
- mes "Christmas more happy!!!";
+ mes "A sweet carol always makes Christmas more happy!!!";
next;
mes "[Santa Claus]";
- mes "Yes indeed Carolling spreads Joy";
- mes "throughout the world?";
+ mes "Yes indeed Carolling spreads Joy throughout the world?";
close;
case 2:
@@ -559,75 +461,53 @@ prontera,226,306,4 script Carolling#iROxmas08 79,{
}
next;
mes "[Santa Claus]";
- mes "But you should be wary of a fake";
- mes "Santa romaing around.";
- mes "Have you heard of Antonio, who";
- mes "invades villages every Christmas?";
+ mes "But you should be wary of a fake Santa romaing around.";
+ mes "Have you heard of Antonio, who invades villages every Christmas?";
next;
mes "[Santa Claus]";
- mes "He has stolen my gifts, as well as";
- mes "attacked adventurers around Toy and";
- mes "Lutie field.";
+ mes "He has stolen my gifts, as well as attacked adventurers around Toy and Lutie field.";
next;
mes "[Santa Claus]";
- mes "A bad Santa ruins us good Santa's";
- mes "reputations!";
- mes "The World Santa Organization is";
- mes "considering this a grave";
- mes "situation.";
+ mes "A bad Santa ruins us good Santa's reputations!";
+ mes "The World Santa Organization is considering this a grave situation.";
close;
case 3:
mes "[Santa Claus]";
mes "A gift box! That sounds good!";
- mes "It's so exciting to open gift boxes";
- mes "when you wake up on Christmas";
- mes "morning!!!";
+ mes "It's so exciting to open gift boxes when you wake up on Christmas morning!!!";
next;
mes "[Santa Claus]";
- mes "But we have very little gifts now,";
- mes "since Santa Antonio has stolen my";
- mes "gift bag.";
+ mes "But we have very little gifts now, since Santa Antonio has stolen my gift bag.";
next;
mes "[Santa Claus]";
- mes "Many adventurers try to catch up";
- mes "to him, but he is not easy to catch.";
+ mes "Many adventurers try to catch up to him, but he is not easy to catch.";
next;
mes "[Santa Claus]";
- mes "Anyway let those adventurers try to";
- mes "catch him, I have a small game for";
- mes "you.";
+ mes "Anyway let those adventurers try to catch him, I have a small game for you.";
next;
mes "[Santa Claus]";
- mes "I will give you a small gift if you";
- mes "beat me!";
+ mes "I will give you a small gift if you beat me!";
next;
mes "[Santa Claus]";
- mes "Do you want to play a game with";
- mes "me?";
+ mes "Do you want to play a game with me?";
next;
if (select("No, thanks.:Yes, I would.") == 1) {
mes "[Santa Claus]";
- mes "Aww, don't be afraid. If you've";
- mes "been a little naughty this year I";
- mes "won't stuff your stockings with";
- mes "coal.";
+ mes "Aww, don't be afraid.";
+ mes "If you've been a little naughty this year I won't stuff your stockings with coal.";
next;
mes "[Santa Claus]";
- mes "I will stay here throughout the";
- mes "Christmas season, just visit me";
- mes "when you change your mind.";
+ mes "I will stay here throughout the Christmas season, just visit me when you change your mind.";
close;
}
if (gettimetick(2) < SantaCardTime) {
mes "[Santa Claus]";
- mes "Um... You've played the game";
- mes "recently haven't you?";
+ mes "Um... You've played the game recently haven't you?";
next;
mes "[Santa Claus]";
mes "You can try the game once a hour.";
- mes "Please visit me after the one hour";
- mes "has passed.";
+ mes "Please visit me after the one hour has passed.";
close;
}
set .@SantaCardTurn,0;
@@ -636,40 +516,35 @@ prontera,226,306,4 script Carolling#iROxmas08 79,{
mes "Wow! You're so cool!";
next;
mes "[Santa Claus]";
- mes "Let me explain how to play this";
- mes "game.";
+ mes "Let me explain how to play this game.";
next;
mes "[Santa Claus]";
- mes "It's quite simple. I will pick one";
- mes "of three cards: Poring Card,";
- mes "Ghostring Card, and Angeling Card.";
- mes "Guess which card I pick and";
- mes "you're a winner!";
+ mes "It's quite simple.";
+ mes "I will pick one of three cards: Poring Card, Ghostring Card, and Angeling Card.";
+ mes "Guess which card I pick and you're a winner!";
next;
mes "[Santa Claus]";
- mes "If you guess right 3 times out of";
- mes "5, I will give you a gift.";
+ mes "If you guess right 3 times out of 5, I will give you a gift.";
mes "Let's get started!";
next;
while(.@SantaCardTurn != 5) {
emotion 56;
mes "[Santa Claus]";
- mes "First let me shuffle up these";
- mes "cards... Ok!!!";
+ mes "First let me shuffle up these cards... Ok!!!";
next;
- specialeffect 0;
+ specialeffect EF_HIT1;
mes "[Santa Claus]";
mes "One!";
next;
- specialeffect 1;
+ specialeffect EF_HIT2;
mes "[Santa Claus]";
mes "Two!";
next;
- specialeffect 2;
+ specialeffect EF_HIT3;
mes "[Santa Claus]";
mes "Three!";
next;
- specialeffect 18;
+ specialeffect EF_STEAL;
mes "[Santa Claus]";
mes "I'm picking up only one!";
next;
@@ -725,8 +600,7 @@ prontera,226,306,4 script Carolling#iROxmas08 79,{
cutin "",255;
mes "[Santa Claus]";
mes "You're lucky.";
- mes "Can you guess the right card the";
- mes "next time around?";
+ mes "Can you guess the right card the next time around?";
next;
}else{
emotion 0;
@@ -739,8 +613,8 @@ prontera,226,306,4 script Carolling#iROxmas08 79,{
}
if (.@SantaCardWins < 3) {
mes "["+strcharinfo(0)+"]";
- mes "This is just luck. Let me try";
- mes "again!!";
+ mes "This is just luck.";
+ mes "Let me try again!!";
next;
mes "[Santa Claus]";
mes "Whenever you want.";
@@ -750,9 +624,8 @@ prontera,226,306,4 script Carolling#iROxmas08 79,{
mes "You're so good!";
next;
mes "[Santa Claus]";
- mes "Now this gift is for you. Put your";
- mes "hand into the bag and pick only";
- mes "one.";
+ mes "Now this gift is for you.";
+ mes "Put your hand into the bag and pick only one.";
set .@SantaCardPrize, rand(1,12);
next;
if (.@SantaCardPrize == 1) {
@@ -793,24 +666,19 @@ prontera,226,306,4 script Carolling#iROxmas08 79,{
}
set SantaCardTime,gettimetick(2)+3600;
mes "[Santa Claus]";
- mes "Good job! Thanks for playing the";
- mes "card game with me! Merry";
- mes "Christmas!";
+ mes "Good job! Thanks for playing the card game with me!";
+ mes "Merry Christmas!";
close;
}
case 4:
mes "[Santa Claus]";
- mes "Do you mean that ever so";
- mes "fashionable costume for Santa's and";
- mes "youngsters!?!";
- mes "Light-weight, fashionable, and";
- mes "keeps you warm!";
+ mes "Do you mean that ever so fashionable costume for Santa's and youngsters!?!";
+ mes "Light-weight, fashionable, and keeps you warm!";
next;
mes "[Santa Claus]";
- mes "There used to be designer who";
- mes "visited my house to make my Santa";
- mes "costumes. Do you have any ideas?";
+ mes "There used to be designer who visited my house to make my Santa costumes.";
+ mes "Do you have any ideas?";
close;
case 5:
@@ -835,10 +703,8 @@ prontera,226,306,4 script Carolling#iROxmas08 79,{
mes "...";
next;
mes "[Santa Claus]";
- mes "You should open your heart to the";
- mes "spirit of Christmas!";
- mes "Once you do, I know you'll be able";
- mes "to think of something.";
+ mes "You should open your heart to the spirit of Christmas!";
+ mes "Once you do, I know you'll be able to think of something.";
close;
}
}
@@ -854,32 +720,25 @@ morocc,158,104,4 duplicate(08santa) Santa Claus#0805 718
// =====================================================
xmas_in,89,92,4 script Louise Kim#iROxmas08 714,{
mes "[Louise Kim]";
- mes "I always thought about how boring";
- mes "Santa Claus is wearing a too boring";
- mes "costume. Too boring!";
+ mes "I always thought about how boring Santa Claus is wearing a too boring costume.";
+ mes "Too boring!";
next;
mes "[Louise Kim]";
- mes "I could make a glamorous style for";
- mes "him!";
+ mes "I could make a glamorous style for him!";
next;
mes "[Louise Kim]";
- mes "I once made a costume for";
- mes "the notorious figure Antonio!";
- mes "The reason catching up to him";
- mes "is so hard, is that his clothes";
- mes "have been given strong power!";
+ mes "I once made a costume for the notorious figure Antonio!";
+ mes "The reason catching up to him is so hard, is that his clothes have been given strong power!";
mes "I blessed them with good luck!";
next;
emotion 3;
mes "[Louise Kim]";
mes "Preta Porter!!";
- mes "Which is quite luxurious";
- mes "but sold at good price ~";
+ mes "Which is quite luxurious but sold at good price ~";
next;
mes "[Louise Kim]";
- mes "Hey loosers! You can share my sense";
- mes "of fashion and wear my look if you";
- mes "run a light mission for me.";
+ mes "Hey loosers!";
+ mes "You can share my sense of fashion and wear my look if you run a light mission for me.";
next;
mes "[Louise Kim]";
mes "Are you interested?";
@@ -887,15 +746,12 @@ xmas_in,89,92,4 script Louise Kim#iROxmas08 714,{
if (select("Nope.:Yes, please.") == 1) {
mes "[Louise Kim]";
mes "Ah!";
- mes "You're silly! You lost your big";
- mes "chance!";
+ mes "You're silly! You lost your big chance!";
next;
emotion 18;
mes "[Louise Kim]";
- mes "Come to me later if you";
- mes "want to get the mission.";
- mes "I, Louise Kim, am generous";
- mes "enough to accept you next time.";
+ mes "Come to me later if you want to get the mission.";
+ mes "I, Louise Kim, am generous enough to accept you next time.";
close;
}
mes "[Louise Kim]";
@@ -904,13 +760,10 @@ xmas_in,89,92,4 script Louise Kim#iROxmas08 714,{
mes "[Louise Kim]";
mes "Don't worry about this mission.";
mes "It's not that difficult.";
- mes "I'm only in need of some";
- mes "materials. Things that are";
- mes "beyond my ability...";
+ mes "I'm only in need of some materials. Things that are beyond my ability...";
next;
mes "[Louise Kim]";
- mes "Anyway, can you bring me some";
- mes "stuff?";
+ mes "Anyway, can you bring me some stuff?";
next;
if (select("Why not? What do you need?:Sorry, no time.") == 2) {
emotion 18;
@@ -922,25 +775,18 @@ xmas_in,89,92,4 script Louise Kim#iROxmas08 714,{
}
mes "[Louise Kim]";
mes "All right, you're cool!!";
- mes "You need to bring me: ^0000FFCotton Shirt,";
- mes "3 Red Potion, Holy Water, 4 Wrapping";
- mes "Paper, Wrapping Lace^000000..";
+ mes "You need to bring me: ^0000FFCotton Shirt, 3 Red Potion, Holy Water, 4 Wrapping Paper, Wrapping Lace^000000.";
next;
mes "[Louise Kim]";
- mes "If you bring me all that stuff, I";
- mes "can make you a glamorous Santa";
- mes "costume.";
+ mes "If you bring me all that stuff, I can make you a glamorous Santa costume.";
next;
if (countitem(2301) < 1 || countitem(501) < 3 || countitem(523) < 1 || countitem(7175) < 4 || countitem(7174) < 1) {
mes "[Louise Kim]";
- mes "If you were to bring me all the";
- mes "stuff, I would make you a wonderful";
- mes "costume, for free...";
+ mes "If you were to bring me all the stuff, I would make you a wonderful costume, for free...";
next;
emotion 3;
mes "[Louise Kim]";
- mes "Please see me again if you are";
- mes "interested.";
+ mes "Please see me again if you are interested.";
close;
}else{
select("Here you are.");
@@ -948,20 +794,18 @@ xmas_in,89,92,4 script Louise Kim#iROxmas08 714,{
mes "[Louise Kim]";
mes "Oh! Good!";
mes "Let's not delay.";
- mes "I will show you my limitless";
- mes "ability.";
+ mes "I will show you my limitless ability.";
next;
mes "-She pours everything in a pot-";
mes "-even the shirt goes in!-";
mes "-She takes it out with skill-";
mes "-and many blessings she sings.-";
next;
- specialeffect 42;
+ specialeffect EF_BLESSING;
emotion 2;
mes "[Louise Kim]";
mes "By artist, Louise Kim!";
- mes "All over the world will be blessed";
- mes "tonight!";
+ mes "All over the world will be blessed tonight!";
next;
mes "-Pour red potion in another pot-";
mes "-then stir all of its parts.-";
@@ -971,20 +815,19 @@ xmas_in,89,92,4 script Louise Kim#iROxmas08 714,{
mes "-String by string-";
mes "-Count your blessings and sing!-";
next;
- specialeffect 75;
+ specialeffect EF_GLORIA;
emotion 2;
mes "[Louise Kim]";
mes "By artist, Louise Kim!";
- mes "All over the world will be blessed";
- mes "tonight!";
+ mes "All over the world will be blessed tonight!";
next;
mes "-She is knitting clothes-";
mes "-with a hooked needle-";
mes "-with her great skill.-";
- mes "Spread your blessings,-";
- mes "cheer and goodwill!-";
+ mes "-Spread your blessings,-";
+ mes "-cheer and goodwill!-";
next;
- specialeffect 91;
+ specialeffect EF_BENEDICTIO;
emotion 3;
mes "[Louise Kim]";
mes "This is miraculous!";
@@ -995,14 +838,11 @@ xmas_in,89,92,4 script Louise Kim#iROxmas08 714,{
mes "All right! Isn't it wonderful?";
mes "You can call it what you wish.";
mes "My fashion is radiant.";
- mes "I ain't envious of Designer";
- mes "Pierre.";
+ mes "I ain't envious of Designer Pierre.";
next;
emotion 18;
mes "[Louise Kim]";
- mes "I am supposed to get paid well,";
- mes "however I will just let it";
- mes "be free, since this is Christmas!";
+ mes "I am supposed to get paid well, however I will just let it be free, since this is Christmas!";
next;
delitem 2301,1;
delitem 501,3;
@@ -1011,9 +851,7 @@ xmas_in,89,92,4 script Louise Kim#iROxmas08 714,{
delitem 7174,1;
getitem 12132,1;
mes "[Louise Kim]";
- mes "Go brag about these wonderful";
- mes "clothes. There wouldn't be";
- mes "any without me, Louise Kim.";
+ mes "Go brag about these wonderful clothes. There wouldn't be any without me, Louise Kim.";
close;
}
}
diff --git a/npc/events/gdevent_aru.txt b/npc/events/gdevent_aru.txt
index e18495620..1c6c70d95 100644
--- a/npc/events/gdevent_aru.txt
+++ b/npc/events/gdevent_aru.txt
@@ -1,10 +1,26 @@
+//===== eAthena Script =======================================
+//= Guild dungeon event, Arunafeltz.
+//===== By: ==================================================
+//= L0ne_W0lf
+//===== Current Version: =====================================
+//= 1.1
+//===== Compatible With: =====================================
+//= eAthena SVN
+//===== Description: =========================================
+//= Guild dungeon event, Arunafeltz. Retrieve Morestone's
+//= pickaxe from Kublin.
+//===== Additional Comments: =================================
+//= 1.0 First version
+//= 1.1 Changed spawn timer to 1 hour. [L0ne_w0lf]
+//============================================================
+
arug_dun01,1,1,1 script Monster Controler#aru_gd 81,{
OnInit:
donpcevent "Monster Controler1#aru::OnKill";
initnpctimer;
end;
-OnTimer10000:
+OnTimer3600000:
donpcevent "Monster Controler1#aru::OnEnable";
mapannounce "arug_dun01", "Kublin: Aargh!",bc_map,"0x99CC00";
mapannounce "arug_dun01", "Morestone: Stop righ there! You thief!",bc_map,"0x99CC00";
diff --git a/npc/events/gdevent_sch.txt b/npc/events/gdevent_sch.txt
index 011d0acd7..9f2064afd 100644
--- a/npc/events/gdevent_sch.txt
+++ b/npc/events/gdevent_sch.txt
@@ -1,10 +1,26 @@
+//===== eAthena Script =======================================
+//= Guild dungeon event, Schwaltzvalt.
+//===== By: ==================================================
+//= L0ne_W0lf
+//===== Current Version: =====================================
+//= 1.1
+//===== Compatible With: =====================================
+//= eAthena SVN
+//===== Description: =========================================
+//= Guild dungeon event, Schwaltzvalt. Retrieve Morestone's
+//= pickaxe from Kublin.
+//===== Additional Comments: =================================
+//= 1.0 First version
+//= 1.1 Changed spawn timer to 1 hour. [L0ne_w0lf]
+//============================================================
+
schg_dun01,1,1,1 script Monster Controler#sch_gd 81,{
OnInit:
donpcevent "Monster Controler1#sch::OnKill";
initnpctimer;
end;
-OnTimer10000:
+OnTimer3600000:
donpcevent "Monster Controler1#sch::OnEnable";
mapannounce "schg_dun01", "Kublin: Aargh!",bc_map,"0x99CC00";
mapannounce "schg_dun01", "Morestone: Stop righ there! You thief!",bc_map,"0x99CC00";
diff --git a/npc/events/halloween_2008.txt b/npc/events/halloween_2008.txt
index 33f54b411..9f467ae09 100644
--- a/npc/events/halloween_2008.txt
+++ b/npc/events/halloween_2008.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= Kisuka
//===== Current Version: =====================================
-//= 1.0
+//= 1.1
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -14,6 +14,7 @@
//= You must enable the event monsters in mob_db2.
//===== Additional Comments: =================================
//= 1.0 First version. [Kisuka]
+//= 1.1 Some small changes. [Kisuka]
//============================================================
payon,162,176,4 script Halloween Magician#iRO08 704,{
@@ -21,15 +22,12 @@ payon,162,176,4 script Halloween Magician#iRO08 704,{
if(Hallow08 < 1) {
mes "[Halloween Magician]";
mes "Kkkkkkkkk!";
- mes "I have a special event this";
- mes "Halloween that tests your luck and";
- mes "agility.";
+ mes "I have a special event this Halloween that tests your luck and agility.";
mes "Are you interested?";
next;
mes "[Halloween Magician]";
mes "Come on! Don't be a wuss!";
- mes "If you collect enough tickets";
- mes "you can get good prizes!";
+ mes "If you collect enough tickets you can get good prizes!";
mes "So what do you say?";
next;
goto MainMenu;
@@ -60,56 +58,40 @@ payon,162,176,4 script Halloween Magician#iRO08 704,{
set Hallow08Kill,0;
mes "[Halloween Magician]";
mes "As I promised";
- mes "You can get Halloween tickets";
- mes "for cool items.";
+ mes "You can get Halloween tickets for cool items.";
close;
}
if(Hallow08 > 0) {
mes "[Halloween Magician]";
- mes "Well, do you want to hear the rules";
- mes "again or,";
- mes "just get back to it...";
+ mes "Well, do you want to hear the rules again or, just get back to it...";
next;
goto MainMenu2;
}
Rules:
mes "[Halloween Magician]";
- mes "This village is like a virtual";
- mes "Payon. There are zombies and ghouls";
- mes "roaming around";
- mes "and three southern exits, but only";
- mes "one works.";
+ mes "This village is like a virtual Payon.";
+ mes "There are zombies and ghouls roaming around and three southern exits, but only one works.";
mes "That's up to you to find out.";
next;
mes "[Halloween Magician]";
- mes "You can't use any skills";
- mes "to kill the ghouls or zombies.";
+ mes "You can't use any skills to kill the ghouls or zombies.";
mes "And one more thing...";
mes "you shouldn't forget...";
next;
mes "[Halloween Magician]";
- mes "All participants";
- mes "should be wearing nothing.";
- mes "Put all belongings in your storage";
- mes "and come back here when your weight";
- mes "is '0'.";
+ mes "All participants should be wearing nothing.";
+ mes "Put all belongings in your storage and come back here when your weight is '0'.";
next;
mes "[Halloween Magician]";
mes "Oh and one more thing!";
- mes "You can't be riding a PecoPeco or";
- mes "have a Cart.";
- mes "If you are, then I will remove them";
- mes "before you enter.";
+ mes "You can't be riding a PecoPeco or have a Cart.";
+ mes "If you are, then I will remove them before you enter.";
mes "Got it?";
next;
mes "[Halloween Magician]";
- mes "Remember, there are three exits but";
- mes "only one works randomly,";
- mes "the zombies and ghouls roaming";
- mes "around there can't be killed";
- mes "and you can't be wearing anything.";
+ mes "Remember, there are three exits but only one works randomly, the zombies and ghouls roaming around there can't be killed and you can't be wearing anything.";
next;
if (Hallow08 > 0) {
mes "[Halloween Magician]";
@@ -128,26 +110,21 @@ payon,162,176,4 script Halloween Magician#iRO08 704,{
if (Weight > 0) {
mes "[Halloween Magician]";
mes "Gosh!";
- mes "There's always a black sheep";
- mes "anywhere.";
+ mes "There's always a black sheep anywhere.";
next;
mes "[Halloween Magician]";
- mes "You think I wouldn't notice that";
- mes "your weight is above '0'?";
+ mes "You think I wouldn't notice that your weight is above '0'?";
mes "You're overweight...";
close;
}else{
mes "[Halloween Magician]";
- mes "You seem good to go,";
- mes "and your weight is just right.";
+ mes "You seem good to go, and your weight is just right.";
next;
mes "[Halloween Magician]";
- mes "I was quite swamped with my work,";
- mes "so I'm exhausted.";
+ mes "I was quite swamped with my work, so I'm exhausted.";
next;
mes "[Halloween Magician]";
- mes "I sometimes forget to send you";
- mes "there...";
+ mes "I sometimes forget to send you there...";
next;
mes "[Halloween Magician]";
mes "I hope you come back well.";
@@ -166,13 +143,11 @@ payon,162,176,4 script Halloween Magician#iRO08 704,{
TicketExchange:
mes "[Halloween Magician]";
- mes "You want to exchange tickets for";
- mes "prizes?";
+ mes "You want to exchange tickets for prizes?";
mes "Good job! Kkkkkk!";
next;
mes "[Halloween Magician]";
- mes "Lemme tell you what items you can";
- mes "exchange for.";
+ mes "Lemme tell you what items you can exchange for.";
next;
mes "[Halloween Magician]";
mes "5 tickets for Pumpkin Pie.";
@@ -182,8 +157,7 @@ payon,162,176,4 script Halloween Magician#iRO08 704,{
mes "200 tickets for Old Card Album.";
next;
mes "[Halloween Magician]";
- mes "What would you like to exchange";
- mes "for?";
+ mes "What would you like to exchange for?";
next;
switch(select("Pumpkin Pie:Pumpkin-Head:Old Blue Box:Old Purple Box:Old Card Album")) {
case 1:
@@ -248,8 +222,7 @@ payon,162,176,4 script Halloween Magician#iRO08 704,{
mes "[Halloween Magician]";
mes "You don't have enough tickets!";
mes "Can't you even count?";
- mes "Please come here with the right";
- mes "number of tickets.";
+ mes "Please come here with the right number of tickets.";
close;
Enough:
diff --git a/npc/events/valentinesday_2009.txt b/npc/events/valentinesday_2009.txt
index 24eb24e01..a9db606aa 100644
--- a/npc/events/valentinesday_2009.txt
+++ b/npc/events/valentinesday_2009.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= Kisuka
//===== Current Version: =====================================
-//= 1.2
+//= 1.3
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -20,6 +20,7 @@
//===== Additional Comments: =================================
//= 1.0 First version. [Kisuka]
//= 1.1-1.2 Fixed exploits with unlimited rings and non deleting choco [Lupus]
+//= 1.3 Some Changes. [Kisuka]
//============================================================
// Marco Bassinio (Chocolate/Chocolate Box maker)
@@ -37,17 +38,12 @@ prontera,164,174,4 script Trader#Val09 58,{
case 1:
mes "[Marco Bassinio]";
mes "Ahaha, my dear.";
- mes "This chocolate is";
- mes "nothing like others.";
- mes "Every piece bears the";
- mes "devotion of the person";
- mes "who made it!";
+ mes "This chocolate is nothing like others.";
+ mes "Every piece bears the devotion of the person who made it!";
next;
mes "[Marco Bassinio]";
- mes "So, that's why I can't sell";
- mes "more than 5 of them at a time.";
- mes "If you really really want more,";
- mes "then talk to me again.";
+ mes "So, that's why I can't sell more than 5 of them at a time.";
+ mes "If you really really want more, then talk to me again.";
mes "How many do you want anyway?";
next;
while(.@input <= 0 || .@input > 5) {
@@ -55,29 +51,22 @@ prontera,164,174,4 script Trader#Val09 58,{
if (.@input < 1) {
mes "[Marco Bassinio]";
mes "Oh, it's such a shame!";
- mes "I'm sure you'll miss";
- mes "this opportunity and";
- mes "regret you didn't buy it.";
+ mes "I'm sure you'll miss this opportunity and regret you didn't buy it.";
next;
mes "[Marco Bassinio]";
- mes "Remember, you can never";
- mes "find this anywhere else!";
- mes "Come back anytime,";
- mes "when you change your mind.";
+ mes "Remember, you can never find this anywhere else!";
+ mes "Come back anytime, when you change your mind.";
close;
}
if (.@input > 5) {
mes "[Marco Bassinio]";
mes "Ugh.. Didn't I tell you?";
mes "5 is the maximum!";
- mes "I can't sell more than";
- mes "that to the same person.";
+ mes "I can't sell more than that to the same person.";
next;
mes "[Marco Bassinio]";
- mes "And you know it's not";
- mes "like an everyday meal.";
- mes "Eating too much is not";
- mes "really good for you.";
+ mes "And you know it's not like an everyday meal.";
+ mes "Eating too much is not really good for you.";
next;
}
}
@@ -90,60 +79,40 @@ prontera,164,174,4 script Trader#Val09 58,{
set .@price, .@input * 5000;
if (Zeny < .@price) {
mes "[Marco Bassinio]";
- mes "Looks like you don't have";
- mes "enough zeny with ya.";
- mes "Maybe you should borrow";
- mes "some zeny from a friend.";
- mes "Cuz, I'm not gonna";
- mes "be here everyday.";
+ mes "Looks like you don't have enough zeny with ya.";
+ mes "Maybe you should borrow some zeny from a friend.";
+ mes "Cuz, I'm not gonna be here everyday.";
close;
}else{
mes "[Marco Bassinio]";
mes "Good for you!";
mes "It's also perfect as a gift!";
- mes "You know you can't get this";
- mes "kind of chocolate normally.";
+ mes "You know you can't get this kind of chocolate normally.";
next;
mes "[Marco Bassinio]";
- mes "If you want more,";
- mes "you should come back.";
- mes "Might be a good idea to";
- mes "buy some more while";
- mes "you have a chance...!";
+ mes "If you want more, you should come back.";
+ mes "Might be a good idea to buy some more while you have a chance...!";
set Zeny,Zeny - .@price;
getitem 558,.@input;
close;
}
case 2:
mes "[Marco Bassinio]";
- mes "If you want to gift-wrap";
- mes "the chocolate, of course,";
- mes "you need chocolate,";
- mes "plus, wrapping paper,";
- mes "wrapping strap and a box.";
+ mes "If you want to gift-wrap the chocolate, of course, you need chocolate, plus, wrapping paper, wrapping strap and a box.";
next;
mes "[Marco Bassinio]";
- mes "You also need to pay";
- mes "500 zeny to carve your";
- mes "name on the box.";
+ mes "You also need to pay 500 zeny to carve your name on the box.";
mes "Are you all prepared...?";
next;
if(countitem(7175) < 1 || countitem(7174) < 1 || countitem(7948) < 1 || Zeny < 500) {
mes "[Marco Bassinio]";
- mes "Hmm.. Looks like you don't";
- mes "have enough materials to";
- mes "decorate the gift box..";
- mes "You can't just put your gift";
- mes "into some plain looking box..";
+ mes "Hmm.. Looks like you don't have enough materials to decorate the gift box..";
+ mes "You can't just put your gift into some plain looking box..";
mes "Don't you think?";
next;
mes "[Marco Bassinio]";
- mes "You need to bring some";
- mes "wrapping paper,";
- mes "wrapping strap, and a box.";
- mes "Oh, also bring 500 zeny,";
- mes "and don't forget to bring your";
- mes "true loving heart with you!!";
+ mes "You need to bring some wrapping paper, wrapping strap, and a box.";
+ mes "Oh, also bring 500 zeny, and don't forget to bring your true loving heart with you!!";
close;
}
if(countitem(558) < 1) {
@@ -153,10 +122,7 @@ prontera,164,174,4 script Trader#Val09 58,{
mes "You know I'm not an alchemist or anything.";
next;
mes "[Marco Bassinio]";
- mes "You're not saying that you";
- mes "want an empty chocolate box";
- mes "without any chocolate in it,";
- mes "am I right?";
+ mes "You're not saying that you want an empty chocolate box without any chocolate in it, am I right?";
close;
}
if (!checkweight(12744,1)) {
@@ -167,11 +133,9 @@ prontera,164,174,4 script Trader#Val09 58,{
}
mes "[Marco Bassinio]";
mes "Here, look!";
- mes "It's your chocolate box";
- mes "with your name on it.";
+ mes "It's your chocolate box with your name on it.";
mes "Isn't it fabulous?";
- mes "See, your name looks";
- mes "great on the box!";
+ mes "See, your name looks great on the box!";
next;
delitem 558,1;
delitem 7175,1;
@@ -186,15 +150,11 @@ prontera,164,174,4 script Trader#Val09 58,{
case 3:
mes "[Marco Bassinio]";
mes "Oh, it's such a shame!";
- mes "I'm sure you'll miss";
- mes "this opportunity and";
- mes "regret you didn't buy it.";
+ mes "I'm sure you'll miss this opportunity and regret you didn't buy it.";
next;
mes "[Marco Bassinio]";
- mes "Remember, you can never";
- mes "find this anywhere else!";
- mes "Come back anytime,";
- mes "when you change your mind.";
+ mes "Remember, you can never find this anywhere else!";
+ mes "Come back anytime, when you change your mind.";
close;
}
}
@@ -203,9 +163,7 @@ prontera,164,174,4 script Trader#Val09 58,{
prontera,147,171,5 script Packs Trader#Val09 58,{
mes "[Packs Trader]";
mes "Hello.";
- mes "I am a Packs Trader,";
- mes "I sell paper boxes and";
- mes "supplies for packing presents.";
+ mes "I am a Packs Trader, I sell paper boxes and supplies for packing presents.";
next;
while(1) {
mes "[Packs Trader]";
@@ -214,18 +172,15 @@ prontera,147,171,5 script Packs Trader#Val09 58,{
switch(select("Packing Paper:Packing Ribbon:Box:Cancel.")) {
case 1:
mes "[Packs Trader]";
- mes "It's 200 zeny for";
- mes "1 Packing Paper.";
+ mes "It's 200 zeny for 1 Packing Paper.";
mes "How many do you want?";
- mes "You can't buy more";
- mes "than 10 items at once.";
+ mes "You can't buy more than 10 items at once.";
next;
input .@input;
if (.@input <= 0) {
mes "[Packs Trader]";
mes "Nothing to buy.";
- mes "Come back when";
- mes "you need something.";
+ mes "Come back when you need something.";
close;
}
if (.@input > 10) {
@@ -250,9 +205,7 @@ prontera,147,171,5 script Packs Trader#Val09 58,{
}else{
mes "[Packs Trader]";
mes "Here they are.";
- mes "Hope it makes your";
- mes "Valentine's Day";
- mes "more pleasing!";
+ mes "Hope it makes your Valentine's Day more pleasing!";
set Zeny,Zeny-.@price;
getitem 7175,.@input;
next;
@@ -260,18 +213,15 @@ prontera,147,171,5 script Packs Trader#Val09 58,{
}
case 2:
mes "[Packs Trader]";
- mes "It's 200 zeny for";
- mes "1 Packing Ribbon.";
+ mes "It's 200 zeny for 1 Packing Ribbon.";
mes "How many do you want?";
- mes "You can't buy more";
- mes "than 10 items at once.";
+ mes "You can't buy more than 10 items at once.";
next;
input .@input;
if (.@input <= 0) {
mes "[Packs Trader]";
mes "Nothing to buy.";
- mes "Come back when";
- mes "you need something.";
+ mes "Come back when you need something.";
close;
}
if (.@input > 10) {
@@ -296,9 +246,7 @@ prontera,147,171,5 script Packs Trader#Val09 58,{
}else{
mes "[Packs Trader]";
mes "Here they are.";
- mes "Hope it makes your";
- mes "Valentine's Day";
- mes "more pleasing!";
+ mes "Hope it makes your Valentine's Day more pleasing!";
set Zeny,Zeny-.@price;
getitem 7174,.@input;
next;
@@ -306,18 +254,15 @@ prontera,147,171,5 script Packs Trader#Val09 58,{
}
case 3:
mes "[Packs Trader]";
- mes "It's 600 zeny for";
- mes "1 Box.";
+ mes "It's 600 zeny for 1 Box.";
mes "How many do you want?";
- mes "You can't buy more";
- mes "than 10 items at once.";
+ mes "You can't buy more than 10 items at once.";
next;
input .@input;
if (.@input <= 0) {
mes "[Packs Trader]";
mes "Nothing to buy.";
- mes "Come back when";
- mes "you need something.";
+ mes "Come back when you need something.";
close;
}
if (.@input > 10) {
@@ -342,9 +287,7 @@ prontera,147,171,5 script Packs Trader#Val09 58,{
}else{
mes "[Packs Trader]";
mes "Here they are.";
- mes "Hope it makes your";
- mes "Valentine's Day";
- mes "more pleasing!";
+ mes "Hope it makes your Valentine's Day more pleasing!";
set Zeny,Zeny-.@price;
getitem 7948,.@input;
next;
@@ -353,8 +296,7 @@ prontera,147,171,5 script Packs Trader#Val09 58,{
case 4:
mes "[Packs Trader]";
mes "Goodbye!";
- mes "And enjoy your";
- mes "Valentine's Day.";
+ mes "And enjoy your Valentine's Day.";
close;
}
}
@@ -364,102 +306,66 @@ prontera,147,171,5 script Packs Trader#Val09 58,{
prontera,154,185,5 script Event Ring Maker#Val09 721,{
if (BaseLevel < 75) {
mes "[Event Ring Maker]";
- mes "Hello, I only make the";
- mes "Valentine rings to those";
- mes "experienced adventurers";
- mes "Level 75 or above.";
+ mes "Hello, I only make the Valentine rings to those experienced adventurer Level 75 or above.";
next;
mes "[Event Ring Maker]";
- mes "You're not fully";
- mes "experienced yet.";
- mes "Come back when you're";
- mes "experienced enough to";
- mes "handle the quests.";
+ mes "You're not fully experienced yet.";
+ mes "Come back when you're experienced enough to handle the quests.";
close;
}
if (iROval09ring >= 1) {
mes "[Event Ring Maker]";
- mes "The box with the ring,";
- mes "carved with your name,";
- mes "is for the one you love.";
+ mes "The box with the ring, carved with your name, is for the one you love.";
next;
mes "[Event Ring Maker]";
- mes "As for the rings that you";
- mes "receive from others, they";
- mes "should all be registered";
- mes "with the Vote Manager.";
- mes "She is standing near";
- mes "the Prontera Fountain.";
+ mes "As for the rings that you receive from others, they should all be registered with the Vote Manager.";
+ mes "She is standing near the Prontera Fountain.";
next;
mes "[Event Ring Maker]";
- mes "Only the most popular";
- mes "male and female are";
- mes "subjected to getting rewards.";
- mes "Be aware, and always";
- mes "try to stay popular!";
+ mes "Only the most popular male and female are subjected to getting rewards.";
+ mes "Be aware, and always try to stay popular!";
close;
}
mes "[Event Ring Maker]";
mes "Hi, there, how are ya?";
- mes "Come to me if you're";
- mes "interested in the event,";
- mes "'Who's Valentine's Hottest?'";
+ mes "Come to me if you're interested in the event, 'Who's Valentine's Hottest?'";
next;
mes "[Event Ring Maker]";
- mes "I make the most precious";
- mes "rings that you can give";
- mes "to your sweethearts.";
- mes "Those rings are very special";
- mes "because I carve";
- mes "your names on them!";
+ mes "I make the most precious rings that you can give to your sweethearts.";
+ mes "Those rings are very special because I carve your names on them!";
next;
mes "[Event Ring Maker]";
mes "Isn't it exciting?";
mes "Isn't it such a brilliant idea?";
- mes "Give these special rings";
- mes "to your sweethearts!";
+ mes "Give these special rings to your sweethearts!";
next;
mes "[Event Ring Maker]";
- mes "You should hurry 'cuz";
- mes "this event will only";
- mes "last for two weeks.";
- mes "Give that special someone";
- mes "a gift of a Valentine's ring.";
+ mes "You should hurry 'cuz this event will only last for two weeks.";
+ mes "Give that special someone a gift of a Valentine's ring.";
next;
mes "[Event Ring Maker]";
- mes "Remember, you can only";
- mes "generate the ring once.";
- mes "You also need Wrapping Paper,";
- mes "Wrapping Strap and a Box";
- mes "to make the ring.";
+ mes "Remember, you can only generate the ring once.";
+ mes "You also need Wrapping Paper, Wrapping Strap and a Box to make the ring.";
next;
mes "[Event Ring Maker]";
- mes "So you better be sure";
- mes "of who you give this to.";
- mes "By the way,";
- mes "It costs 1,000 zeny.";
+ mes "So you better be sure of who you give this to.";
+ mes "By the way, It costs 1,000 zeny.";
mes "Would you like to make one?";
next;
if(select("Hmm.. I gotta give it a second thought...:Sure.") == 1) {
mes "[Event Ring Maker]";
mes "Alrighty!";
- mes "You can't put a rush";
- mes "on such a thing like this.";
- mes "Think about what";
- mes "you truly want.";
+ mes "You can't put a rush on such a thing like this.";
+ mes "Think about what you truly want.";
mes "Just follow your heart!";
close;
}
if(countitem(7175) < 1 || countitem(7174) < 1 || countitem(7948) < 1 || Zeny < 1000) {
mes "[Event Ring Maker]";
- mes "Well, you don't have";
- mes "enough materials";
- mes "to make a gift box.";
- mes "Check what you have,";
- mes "and come back later";
- mes "with all the materials.";
+ mes "Well, you don't have enough materials to make a gift box.";
+ mes "Check what you have, and come back later with all the materials.";
close;
}
mes "[Event Ring Maker]";
@@ -477,51 +383,33 @@ prontera,154,185,5 script Event Ring Maker#Val09 721,{
getnameditem 12743,strcharinfo(0);
}
mes "[Event Ring Maker]";
- mes "Here, the most precious";
- mes "ring in the world!";
- mes "Don't forget, you can never";
- mes "make this ring again.";
+ mes "Here, the most precious ring in the world!";
+ mes "Don't forget, you can never make this ring again.";
next;
mes "[Event Ring Maker]";
- mes "You must pick out the one";
- mes "that you really really love,";
- mes "and give this ring";
- mes "to that person.";
+ mes "You must pick out the one that you really really love, and give this ring to that person.";
next;
mes "[Event Ring Maker]";
- mes "Of course, you've got to";
- mes "get rings from others,";
- mes "that's the way you can";
- mes "participate in the voting, right?";
- mes "Challenge yourself to become";
- mes "Valentine's Hottest!";
+ mes "Of course, you've got to get rings from others, that's the way you can participate in the voting, right?";
+ mes "Challenge yourself to become Valentine's Hottest!";
close;
}
// Valentine Vote Manager (Registers votes)
prontera,157,185,4 script Valentine Vote Manager#v 113,{
mes "[Valentine Vote Manager]";
- mes "Hello, I'm the Valentine's";
- mes "Vote Manager.";
- mes "I'm in charge of collecting";
- mes "rings for this event!";
+ mes "Hello, I'm the Valentine's Vote Manager.";
+ mes "I'm in charge of collecting rings for this event!";
next;
mes "[Valentine Vote Manager]";
- mes "I register the rings";
- mes "you get from others";
- mes "and I calculate the";
- mes "total number of rings.";
+ mes "I register the rings you get from others and I calculate the total number of rings.";
next;
mes "[Valentine Vote Manager]";
- mes "You know what I do besides";
- mes "just counting those rings?";
- mes "I can tell you the adventurer's";
- mes "name who's got the";
- mes "most number of votes.";
+ mes "You know what I do besides just counting those rings?";
+ mes "I can tell you the adventurer's name who's got the most number of votes.";
next;
mes "[Valentine Vote Manager]";
- mes "Plus, you can also find out how";
- mes "many votes he/she got.";
+ mes "Plus, you can also find out how many votes he/she got.";
next;
while (1) {
mes "[Valentine Vote Manager]";
@@ -530,15 +418,10 @@ prontera,157,185,4 script Valentine Vote Manager#v 113,{
switch(select("Please register my rings.:Please count my votes.:Nothing, for now.")) {
case 1:
mes "[Valentine Vote Manager]";
- mes "Please tell me how many";
- mes "rings you want to register.";
+ mes "Please tell me how many rings you want to register.";
next;
mes "[Valentine Vote Manager]";
- mes "When you write the";
- mes "number of the rings,";
- mes "the number shouldn't be";
- mes "larger than the number of";
- mes "rings you actually have.";
+ mes "When you write the number of the rings, the number shouldn't be larger than the number of rings you actually have.";
mes "'0', cancels everything.";
next;
input .@input;
@@ -569,8 +452,7 @@ prontera,157,185,4 script Valentine Vote Manager#v 113,{
}
mes "[Valentine Vote Manager]";
- mes "I'll take those silver rings,";
- mes "and count the votes for you.";
+ mes "I'll take those silver rings, and count the votes for you.";
mes "Thank you for participating.";
delitem 7947,.@input;
set Val09Rings,Val09Rings+.@input;
@@ -598,8 +480,7 @@ prontera,157,185,4 script Valentine Vote Manager#v 113,{
}
mes "[Valentine Vote Manager]";
- mes "I'll take those gold rings,";
- mes "and count the votes for you.";
+ mes "I'll take those gold rings, and count the votes for you.";
mes "Thank you for participating.";
delitem 7946,.@input;
set Val09Rings,Val09Rings+.@input;
@@ -613,8 +494,7 @@ prontera,157,185,4 script Valentine Vote Manager#v 113,{
case 2:
mes "[Valentine Vote Manager]";
mes "Let's see...";
- mes "You have registered..";
- mes ".."+Val09Rings+" rings so far.";
+ mes "You have registered...."+Val09Rings+" rings so far.";
mes "and...";
next;
mes "[Valentine Vote Manager]";
@@ -629,8 +509,7 @@ prontera,157,185,4 script Valentine Vote Manager#v 113,{
mes "[Valentine Vote Manager]";
mes "Hey, you can be popular too!";
mes "Anyone can... really!";
- mes "Though you have to try a lot";
- mes "harder, but still~ Hahaha!";
+ mes "Though you have to try a lot harder, but still~ Hahaha!";
close;
}
}
@@ -640,16 +519,12 @@ prontera,157,185,4 script Valentine Vote Manager#v 113,{
prt_castle,42,35,3 script Dessert Manager#Val09 47,{
if (Sex) {
mes "[Charles Orleans]";
- mes "Monsieur~! What brings";
- mes "you to my beautiful atelier?";
+ mes "Monsieur~! What brings you to my beautiful atelier?";
mes "What is it that you want?";
- mes "Well, my sparkling eyes";
- mes "get dried and lose their shine";
- mes "if not for the pretty little lady.";
+ mes "Well, my sparkling eyes get dried and lose their shine if not for the pretty little lady.";
next;
mes "[Charles Orleans]";
- mes "Please leave me alone unless";
- mes "you have business with me.";
+ mes "Please leave me alone unless you have business with me.";
mes "Haaaa~ I'm a busy person.";
mes "Don't bother me....";
mes "Annoying, annoying, annoying~~!";
@@ -658,11 +533,8 @@ prt_castle,42,35,3 script Dessert Manager#Val09 47,{
mes "[Charles Orleans]";
mes "Oh, Mademoiselle!";
- mes "This little trifling space";
- mes "felt like heaven the";
- mes "minute you walked in!";
- mes "Can I help you with";
- mes "anything, if it's alright?";
+ mes "This little trifling space felt like heaven the minute you walked in!";
+ mes "Can I help you with anything, if it's alright?";
next;
if(select("Please, make me some chocolate.:Don't bother. I'm just passing by.") == 2) {
mes "[Charles Orleans]";
@@ -680,51 +552,36 @@ prt_castle,42,35,3 script Dessert Manager#Val09 47,{
if(countitem(558) < 3) {
mes "[Charles Orleans]";
mes "Ahhh, Mademoiselle.";
- mes "I'm not an alchemist,";
- mes "or a magician.";
- mes "I don't just make chocolate";
- mes "out of anything.";
+ mes "I'm not an alchemist, or a magician.";
+ mes "I don't just make chocolate out of anything.";
next;
mes "[Charles Orleans]";
- mes "I always think of making";
- mes "chocolate as artistic work.";
+ mes "I always think of making chocolate as artistic work.";
mes "You see, I'm no ordinary cook...";
mes "I make chocolate with feelings..";
mes "messages of loving hearts..";
next;
mes "[Charles Orleans]";
mes "I make masterpieces.";
- mes "No one can imitate";
- mes "the looks and the taste.";
- mes "Yes, it's nothing like";
- mes "ordinary chocolate!";
+ mes "No one can imitate the looks and the taste.";
+ mes "Yes, it's nothing like ordinary chocolate!";
next;
mes "[Charles Orleans]";
- mes "I'm afraid I can't make it";
- mes "and prove it to you now.";
+ mes "I'm afraid I can't make it and prove it to you now.";
mes "This is really a shame!";
next;
mes "[Charles Orleans]";
- mes "I really want to thank";
- mes "you for visiting me";
- mes "and if you only bring";
- mes "^3152ff3 Chocolates^000000,";
- mes "I'll make you chocolate";
- mes "like you've never seen...";
+ mes "I really want to thank you for visiting me and if you only bring ^3152ff3 Chocolates^000000, I'll make you chocolate like you've never seen...";
next;
mes "[Charles Orleans]";
mes "never tasted before...";
- mes "Mademoiselle, with your spirit,";
- mes "I'm sure you can bring";
- mes "3 pieces of chocolate.";
+ mes "Mademoiselle, with your spirit, I'm sure you can bring 3 pieces of chocolate.";
mes "I have no doubt at all.";
next;
mes "[Charles Orleans]";
mes "So... what do you think?";
mes "Can you bring ^3152ff3 Chocolates^000000?";
- mes "I could get them myself,";
- mes "but I'm tied up with so much";
- mes "work as you see right now.";
+ mes "I could get them myself, but I'm tied up with so much work as you see right now.";
next;
mes "[Charles Orleans]";
mes "Adios, Mademoiselle.....";
@@ -739,28 +596,20 @@ prt_castle,42,35,3 script Dessert Manager#Val09 47,{
}
mes "[Charles Orleans]";
mes "Oh, Mademoiselle!";
- mes "I'll make the best chocolate";
- mes "with the pieces you've brought.";
- mes "I'm going to put the light of";
- mes "your eyes into this chocolate";
- mes "that no one can resist.";
+ mes "I'll make the best chocolate with the pieces you've brought.";
+ mes "I'm going to put the light of your eyes into this chocolate that no one can resist.";
next;
mes "[Charles Orleans]";
- mes "It'll be stronger than a";
- mes "sweet sweet love potion.....";
+ mes "It'll be stronger than a sweet sweet love potion.....";
next;
mes "[Charles Orleans]";
mes "Un, Deux, Trois, Quatre.....";
- mes "Just like the ugly duckling that";
- mes "turned to a beautiful swan-";
- mes "Ordinary chocolate pieces are";
- mes "becoming a piece of art!";
+ mes "Just like the ugly duckling that turned to a beautiful swan-";
+ mes "Ordinary chocolate pieces are becoming a piece of art!";
next;
mes "[Charles Orleans]";
mes "They're changing!";
- mes "They're getting warm,";
- mes "softly changing the shape,";
- mes "getting stronger again!";
+ mes "They're getting warm, softly changing the shape, getting stronger again!";
mes "Oh, is it a master piece or";
mes "what...!!";
next;
@@ -774,10 +623,7 @@ prt_castle,42,35,3 script Dessert Manager#Val09 47,{
next;
mes "[Charles Orleans]";
mes "Alright. Mademoiselle,";
- mes "I hope this is just";
- mes "what you wanted,";
- mes "for it bears your";
- mes "beautiful heart inside.";
+ mes "I hope this is just what you wanted, for it bears your beautiful heart inside.";
close;
}
diff --git a/npc/instances/EndlessTower.txt b/npc/instances/EndlessTower.txt
index b1dc002b9..495b367d2 100644
--- a/npc/instances/EndlessTower.txt
+++ b/npc/instances/EndlessTower.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= L0ne_W0lf
//===== Current Version: =====================================
-//= 1.5
+//= 1.6
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -21,6 +21,8 @@
//= You may need to update your questid2display.
//= Changed White lady spawn to MVP White Lady. (bugreport:4601)
//= 1.5 Corrected some grammar and typos.
+//= 1.6 Corrected the tower re-entry blocked condition. (bugreport:4677) [L0ne_W0lf]
+//= Corrected floor 75 warp disabling the wrong NPC. (bugreport:4711)
//============================================================
alberta,214,77,6 script Captain Janssen 709,{
@@ -352,7 +354,7 @@ e_tower,81,105,0 script Tower Protection Stone 406,{
}
close;
}
- else if ((.@etower_timer >= 0) && (.@etower_timer2 == 2)) {
+ else if ((.@etower_timer >= 0) && (.@etower_timer < 2) && (.@etower_timer2 == 2)) {
mes "Due to the tower's aftereffects, you cannot enter the dungeon right now, " + .@dun_h + "hours " + .@dun_m + "minutes " + .@dun_s + "seconds left to enter the next dungeon.";
next;
mes "It is dangerous here. Let me move you to Alberta.";
@@ -2807,11 +2809,11 @@ OnTimer120000:
3@tower,355,51,0 script 75FGate102tower-2 45,2,2,{
OnInstanceInit:
- disablenpc instance_npcname("75FGate102tower", instance_id());
+ disablenpc instance_npcname("75FGate102tower-2", instance_id());
end;
OnEnable:
- enablenpc instance_npcname("75FGate102tower", instance_id());
+ enablenpc instance_npcname("75FGate102tower-2", instance_id());
end;
OnTouch_:
diff --git a/npc/merchants/icecream.txt b/npc/merchants/icecream.txt
index eb1dd0c63..e6a4deb23 100644
--- a/npc/merchants/icecream.txt
+++ b/npc/merchants/icecream.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= KOOK SWU, Kisuka
//===== Current Version: =====================================
-//= 1.3
+//= 1.5
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -12,10 +12,11 @@
//= 1.1 Optimized, changed overlapping coords in Alberta [Lupus]
//= 1.2 According to the patch, IceCream seller has been removed from Morocc [Lupus]
//= 1.3 No more label menu and updated to match AEGIS script. [Kisuka]
+//= 1.4 Duplicates now spawn from floating NPCs. [L0ne_W0lf]
+//= 1.5 Fixed small checkweight issue. [Kisuka]
//============================================================
-// Alberta
-alberta,120,45,2 script Ice Cream Maker::IceCreamer 85,{
+- script Ice Cream Maker::IceCreamer -1,{
mes "[Ice Cream Maker]";
mes "Fresh Ice Cream made with snow from Lutie!";
mes "Enjoy it now, it won't be on sale for long!";
@@ -62,7 +63,7 @@ alberta,120,45,2 script Ice Cream Maker::IceCreamer 85,{
mes "Price is ^3355FF100 Zeny^000000 per ice cream.";
close;
}
- if(checkweight(536,.@amount) == 0) {
+ if(checkweight(536,.@input) == 0) {
mes "[Ice Cream Maker]";
mes "Dear customer,you look like you're carrying a lot.";
mes "Ice Cream is fine,";
@@ -75,6 +76,9 @@ alberta,120,45,2 script Ice Cream Maker::IceCreamer 85,{
close;
}
+// Alberta
+alberta,120,45,2 duplicate(IceCreamer) Ice Cream Maker#1 85
+
// Morroc Field
moc_fild16,88,304,4 duplicate(IceCreamer) Ice Cream Maker#2 85
diff --git a/npc/merchants/socket_enchant.txt b/npc/merchants/socket_enchant.txt
index 8f8a13b0d..9e9af6d68 100644
--- a/npc/merchants/socket_enchant.txt
+++ b/npc/merchants/socket_enchant.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= eAthena dev team
//===== Current Version: =====================================
-//= 1.9
+//= 2.0
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -26,9 +26,10 @@
//= 1.8 Added missing Gae Bolg and Dragon Slayer. [Kisuka]
//= 1.9 Moved Episode 12 items to separate NPC.
//= Some cleanup & optimization. [Gepard]
+//= 2.0 Duplicates now spawn from floating NPCs. [L0ne_W0lf]
//============================================================
-payon,140,151,5 script Seiyablem#pay 84,{
+- script Seiyablem#dummy::SocketEnchant -1,{
if (checkweight(1201,1) == 0)
{
mes "- Wait a minute !! -";
@@ -333,11 +334,12 @@ function script Func_Socket {
}
}
-lhz_in02,281,35,5 duplicate(Seiyablem#pay) Seiyablem#lhz 84
-prt_in,33,70,5 duplicate(Seiyablem#pay) Seiyablem#prt 84
-morocc,51,41,4 duplicate(Seiyablem#pay) Seiyablem#moc 84
+payon,140,151,5 duplicate(SocketEnchant) Seiyablem#pay 84
+lhz_in02,281,35,5 duplicate(SocketEnchant) Seiyablem#lhz 84
+prt_in,33,70,5 duplicate(SocketEnchant) Seiyablem#prt 84
+morocc,51,41,4 duplicate(SocketEnchant) Seiyablem#moc 84
-prt_in,31,57,1 script Young Man#prt 97,{
+- script Young Man#dummy::SocketMan -1,{
mes "[Young Man]";
mes "I'm considering becoming a Slotting Engineer.";
mes "It's a new field where you can add Slots to equipment, and it'd be cool if I can work in such a lucrative career.";
@@ -354,6 +356,7 @@ prt_in,31,57,1 script Young Man#prt 97,{
close;
}
-payon,143,143,7 duplicate(Young Man#prt) Young Man#pay 97
-morocc,60,42,3 duplicate(Young Man#prt) Young Man#moc 97
-lhz_in02,269,33,5 duplicate(Young Man#prt) Young Man#lhz 97
+prt_in,31,57,1 duplicate(SocketMan) Young Man#prt 97
+payon,143,143,7 duplicate(SocketMan) Young Man#pay 97
+morocc,60,42,3 duplicate(SocketMan) Young Man#moc 97
+lhz_in02,269,33,5 duplicate(SocketMan) Young Man#lhz 97
diff --git a/npc/merchants/socket_enchant2.txt b/npc/merchants/socket_enchant2.txt
index 58b934b24..e7f14c37c 100644
--- a/npc/merchants/socket_enchant2.txt
+++ b/npc/merchants/socket_enchant2.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= Gepard
//===== Current Version: =====================================
-//= 1.0
+//= 1.1
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -11,9 +11,10 @@
//= Adds slots to selected weapons and armor.
//===== Additional Comments: =================================
//= 1.0 First version.
+//= 1.1 Duplicates now spawn from floating NPCs. [L0ne_W0lf]
//============================================================
-payon,236,199,3 script Leablem 86,{
+- script Leablem#dummy::SocketEnchant2 -1,{
if (checkweight(1201,1) == 0)
{
mes "- Wait a seconds !! -";
@@ -377,9 +378,10 @@ payon,236,199,3 script Leablem 86,{
}
}
-lighthalzen,96,137,3 duplicate(Leablem) Leablem#lhz 86
-prontera,244,169,5 duplicate(Leablem) Leablem#prt 86
-moc_ruins,154,86,3 duplicate(Leablem) Leablem#moc 86
+payon,236,199,3 duplicate(SocketEnchant2) Leablem#pay 86,{
+lighthalzen,96,137,3 duplicate(SocketEnchant2) Leablem#lhz 86
+prontera,244,169,5 duplicate(SocketEnchant2) Leablem#prt 86
+moc_ruins,154,86,3 duplicate(SocketEnchant2) Leablem#moc 86
function script Func_Socket2 {
diff --git a/npc/other/auction.txt b/npc/other/auction.txt
index 4a033fa3a..20fcde573 100644
--- a/npc/other/auction.txt
+++ b/npc/other/auction.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= L0ne_W0lf
//===== Current Version: =====================================
-//= 1.2
+//= 1.3
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -13,6 +13,7 @@
//= 1.0 First version, place holders only. [L0ne_W0lf]
//= 1.1 Moved Morroc Auction NPCs to Morroc Ruins. [L0ne_W0lf]
//= 1.2 Warp fixed. Dialog in Ruins/Lighthalzen changed. [Kisuka]
+//= 1.3 Duplicates now spawn from floating NPCs. [L0ne_W0lf]
//============================================================
// Auction House warpers
@@ -72,14 +73,15 @@ function script F_AuctionWarper {
// Sign posts
//============================================================
-moc_ruins,76,176,6 script Information Post#moc::AuctionSign 837,{
+- script Information Post#dum::AuctionSign -1,{
mes "[Information]";
mes "Auction Warp Guide";
close;
}
-prontera,216,120,4 duplicate(AuctionSign) Information Post#prt 837,{
-yuno,131,116,0 duplicate(AuctionSign) Information Post#yuno 837,{
+moc_ruins,76,176,6 duplicate(AuctionSign) Information Post#moc 837
+prontera,216,120,4 duplicate(AuctionSign) Information Post#prt 837
+yuno,131,116,0 duplicate(AuctionSign) Information Post#yuno 837
lighthalzen,207,169,6 duplicate(AuctionSign) Information Post#lhz 837
// Warps
@@ -91,7 +93,7 @@ auction_02,43,17,0 warp auction_enterance_lhz 1,1,lighthalzen,209,169
// Auction House NPCs
//============================================================
-auction_01,182,68,6 script Auction Broker#moc1::AuctionBroker 98,{
+- script Auction Broker#dum::AuctionBroker -1,{
mes "[Auction Broker]";
mes "Welcome to the Auction Hall.";
mes "Would you like to view the goods?";
@@ -114,6 +116,7 @@ auction_01,182,68,6 script Auction Broker#moc1::AuctionBroker 98,{
close;
}
+auction_01,182,68,6 duplicate(AuctionBroker) Auction Broker#moc1 98
auction_01,182,75,0 duplicate(AuctionBroker) Auction Broker#moc2 99
auction_01,177,75,2 duplicate(AuctionBroker) Auction Broker#moc3 98
auction_01,177,68,4 duplicate(AuctionBroker) Auction Broker#moc4 99
diff --git a/npc/other/comodo_gambling.txt b/npc/other/comodo_gambling.txt
index 155e21031..9f563141f 100644
--- a/npc/other/comodo_gambling.txt
+++ b/npc/other/comodo_gambling.txt
@@ -21,6 +21,7 @@
//= Added missing emotions and cutins
//= 1.1- Updated prizes according to 11.1 NPC [Paradox924X]
//= 1.2 Corrected NPC names to fall within proper restrictions. [L0ne_W0lf]
+//= 1.3 Added missing item. [Kisuka]
//============================================================
comodo,219,160,3 script Kachua 91,{
@@ -169,6 +170,7 @@ comodo,219,160,3 script Kachua 91,{
else if (.@gamble2 == 81) set .@item,1560; // Sage's Diary[2]
else if (.@gamble2 == 82) set .@item,1618; // Survivor's Rod[1]
else if (.@gamble2 == 83) set .@item,1620; // Survivor's Rod[1]
+ else if (.@gamble2 > 83 && .@gamble2 < 86) set .@item,1971; // Electric Wire
}
else if ((.@gamble1 > 0) && (.@gamble1 < 201)) set .@item,1201; // Knife[3]
else if ((.@gamble1 > 200) && (.@gamble1 < 301)) set .@item,1101; // Sword[3]
diff --git a/npc/other/mail.txt b/npc/other/mail.txt
index 626efcb0b..778dba4f4 100644
--- a/npc/other/mail.txt
+++ b/npc/other/mail.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= L0ne_W0lf
//===== Current Version: =====================================
-//= 1.5
+//= 1.6
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -17,14 +17,12 @@
//= 1.3a Corrected a typo error. (bugreport:798) [Samuray22]
//= 1.4 Added a Mapflag to prevent mail operations in other maps [Zephyrus]
//= 1.5 Moved Morroc Mail boxes to Morroc Ruins. [L0ne_W0lf]
+//= 1.6 Duplicates now spawn from floating NPCs. [L0ne_W0lf]
//============================================================
-// Allow Mail Inbox reading from
+// Floating mailbox npc that all NPCs duplicate from.
//============================================================
-
-// Prontera
-//============================================================
-prontera,146,86,0 script Mailbox#prt::MailBox 888,{
+- script Mailbox#dummy::MailBox -1,{
mes "[Mailbox]";
mes "If you'd like to use";
mes "the Mailbox Service,";
@@ -57,6 +55,9 @@ prontera,146,86,0 script Mailbox#prt::MailBox 888,{
close;
}
+// Prontera
+//============================================================
+prontera,146,86,0 duplicate(MailBox) Mailbox#prt 888
prontera,275,213,0 duplicate(MailBox) Mailbox#2prt 888
prontera,34,212,0 duplicate(MailBox) Mailbox#3prt 888
diff --git a/npc/other/mercenary_rent.txt b/npc/other/mercenary_rent.txt
index 645f7dfd6..23c3e78c1 100644
--- a/npc/other/mercenary_rent.txt
+++ b/npc/other/mercenary_rent.txt
@@ -1,9 +1,10 @@
//===== eAthena Script =======================================
+//===== eAthena Script =======================================
//= Mercenary related NPCs
//===== By: ==================================================
//= L0ne_W0lf
//===== Current Version: =====================================
-//= 1.2
+//= 1.3
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -14,6 +15,7 @@
//= 1.0 First version. [L0ne_W0lf]
//= 1.1 Optimization. [Zephyrus]
//= 1.2 Removed redundent input. [L0ne_W0lf]
+//= 1.3 Duplicates now spawned from floating NPCs. [L0ne_W0lf]
//============================================================
prontera,41,337,5 script Mercenary Manager#Spear 105,{
@@ -653,7 +655,7 @@ pay_arche,99,167,4 script Mercenary Manager#Bow 732,{
// Mercenary Merchant NPCs
//============================================================
-prontera,30,337,4 script Mercenary Merchant#Spear::MercMerchant 700,{
+- script Mercenary Merchant#dummy::MercMerchant -1,{
mes "[Mercenary Goods Merchant]";
mes "Hello, I sell goods";
mes "that Mercenaries can";
@@ -698,8 +700,10 @@ prontera,30,337,4 script Mercenary Merchant#Spear::MercMerchant 700,{
next;
callfunc "F_PurchaseMercItem",12243,2100;
}
+ close;
}
+prontera,30,337,4 duplicate(MercMerchant) Mercenary Merchant#Spear 700
izlude,56,139,4 duplicate(MercMerchant) Mercenary Merchant#Sword 892
pay_arche,102,167,5 duplicate(MercMerchant) Mercenary Merchant#Bow 879
diff --git a/npc/other/pvp.txt b/npc/other/pvp.txt
index 05c56e2e5..5a7673ce9 100644
--- a/npc/other/pvp.txt
+++ b/npc/other/pvp.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= kobra_k88; L0ne_W0lf
//===== Current Version: =====================================
-//= 1.4
+//= 1.5
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -26,15 +26,12 @@
//= exception of the "Free for all" mode.
//= Added PVP event NPCs.
//= 1.4 Corrected NPC names to fall within proper restrictions. [L0ne_W0lf]
+//= 1.5 Duplicates now spawn from floating NPCs. [L0ne_W0lf]
//============================================================
-// Morroc
+// Floating NPC
//============================================================
-morocc_in,144,138,4 script PVPNarrator#moc 84,{
- callfunc "F_PVPNarrator","morocc_in",141,139;
-}
-
-morocc_in,144,142,4 script Gate Keeper#moc::PVPGateKeeper 83,{
+- script Gate Keeper#dummy::PVPGateKeeper -1,{
mes "[Gate Keeper]";
mes "Glad to be of service.";
mes "I will open the PVP fight";
@@ -114,6 +111,15 @@ morocc_in,144,142,4 script Gate Keeper#moc::PVPGateKeeper 83,{
}
}
+// Morroc
+//============================================================
+morocc_in,144,138,4 script PVPNarrator#moc 84,{
+ callfunc "F_PVPNarrator","morocc_in",141,139;
+}
+
+morocc_in,144,142,4 duplicate(PVPGateKeeper) Gate Keeper#moc 83,{
+
+
// Alberta
//============================================================
alberta_in,22,146,4 script PVP Narrator#alb 84,{
@@ -465,7 +471,7 @@ OnInit:
// Spectator Entrance
//============================================================
-pvp_room,62,85,4 script Spectator's Entrance#1::PVPSpectator 105,{
+- script Spectator's Entrance#dum::PVPSpectator -1,{
if (countitem(7029) == 0) {
mes "[PVP Compete Square Register Staff]";
mes "This is the entrance for viewers.";
@@ -492,6 +498,8 @@ OnInit:
end;
}
+pvp_room,62,85,4 duplicate(PVPSpectator) Spectator's Entrance#1 105
+
pvp_room,70,85,4 duplicate(PVPSpectator) Spectator's Entrance#2 105
pvp_room,78,85,4 duplicate(PVPSpectator) Spectator's Entrance#3 105
@@ -500,7 +508,7 @@ pvp_room,86,85,4 duplicate(PVPSpectator) Spectator's Entrance#4 105
// Spectator Warps
//============================================================
-pvp_2vs2,5,4,0 script Combat Square Staff#1::PVPSpecWarp 45,1,1,{
+- script Combat Square Staff#dum::PVPSpecWarp -1,{
OnTouch:
mes "[Combat Square Staff]";
mes "May I help you?";
@@ -512,6 +520,8 @@ OnTouch:
end;
}
+pvp_2vs2,5,4,0 duplicate(PVPSpecWarp) Combat Square Staff#1 45,1,1,{
+
pvp_2vs2,5,74,0 duplicate(PVPSpecWarp) Combat Square Staff#2 45,1,1
pvp_2vs2,74,74,0 duplicate(PVPSpecWarp) Combat Square Staff#3 45,1,1
diff --git a/npc/quests/newgears/2006_headgear.txt b/npc/quests/newgears/2006_headgear.txt
index e8980b0be..25d69475d 100644
--- a/npc/quests/newgears/2006_headgear.txt
+++ b/npc/quests/newgears/2006_headgear.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= DiviniaRO members, cleaned by reddozen
//===== Current Version: =====================================
-//= 1.3a
+//= 1.4
//===== Compatible With: =====================================
//= SVN eA
//===== Description: =========================================
@@ -21,6 +21,7 @@
//= Fixed some of the names to iRO.
//= 1.3 Fixed some color code bugs in Ghenirhemin. Thanks to yyCC. [L0ne_W0lf]
//= 1.3a Fixed wrong item names (due to copy/paste) [Lupus]
+//= 1.4 Chungwolmang now checks if the last item set should be deleted. (bugreport:4719) [L0ne_W0lf]
//============================================================
//===================== Censor Bar =====================================================
@@ -781,7 +782,8 @@ S_MakeMask:
delitem getarg(1),getarg(2);
delitem getarg(3),getarg(4);
delitem getarg(5),getarg(6);
- delitem getarg(7),getarg(8);
+ if (getarg(0) == 5169)
+ delitem getarg(7),getarg(8);
getitem getarg(0),1;
set moza_tal,0;
mes "[Chungwolmang]";
diff --git a/npc/quests/quests_13_1.txt b/npc/quests/quests_13_1.txt
index e1b885d5d..a85c3173d 100644
--- a/npc/quests/quests_13_1.txt
+++ b/npc/quests/quests_13_1.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= L0ne_W0lf
//===== Current Version: =====================================
-//= 1.6
+//= 1.7
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -33,6 +33,7 @@
//= 1.4 Changed killmonsterall -> killmonster. (bugreport:4131)
//= 1.5 Removed a 'close;' which should have been 'close2'. (bugreport:4276)
//= 1.6 Fixed check in cat hand agent.
+//= 1.7 Moved the close in Cat Hand Service Warps. (bugreport:4079) [L0ne_W0lf]
//============================================================
// Onward to the New World
@@ -8956,8 +8957,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 2:
break;
}
@@ -8972,8 +8973,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 2:
if (Zeny >= 5500) {
set zeny,zeny-5500;
@@ -8982,8 +8983,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 3:
break;
}
@@ -8998,8 +8999,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 2:
if (Zeny >= 5025) {
set zeny,zeny-5025;
@@ -9008,8 +9009,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 3:
if (Zeny >= 5025) {
set zeny,zeny-5025;
@@ -9018,8 +9019,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 4:
break;
}
@@ -9034,8 +9035,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 2:
if (Zeny >= 5025) {
set zeny,zeny-5025;
@@ -9044,8 +9045,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 3:
if (Zeny >= 5025) {
set zeny,zeny-5025;
@@ -9054,8 +9055,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 4:
if (Zeny >= 5025) {
set zeny,zeny-5025;
@@ -9064,8 +9065,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 5:
break;
}
@@ -9080,8 +9081,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 2:
if (Zeny >= 4765) {
set zeny,zeny-4765;
@@ -9090,8 +9091,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 3:
if (Zeny >= 4765) {
set zeny,zeny-4765;
@@ -9100,8 +9101,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 4:
if (Zeny >= 4765) {
set zeny,zeny-4765;
@@ -9110,8 +9111,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 5:
if (Zeny >= 4765) {
set zeny,zeny-4765;
@@ -9120,8 +9121,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 6:
break;
}
@@ -9136,8 +9137,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 2:
if (Zeny >= 4765) {
set zeny,zeny-4765;
@@ -9146,8 +9147,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 3:
if (Zeny >= 4765) {
set zeny,zeny-4765;
@@ -9156,8 +9157,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 4:
if (Zeny >= 4765) {
set zeny,zeny-4765;
@@ -9166,8 +9167,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 5:
if (Zeny >= 4765) {
set zeny,zeny-4765;
@@ -9176,8 +9177,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 6:
if (Zeny >= 4765) {
set zeny,zeny-4765;
@@ -9186,8 +9187,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 7:
break;
}
@@ -9202,8 +9203,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 2:
if (Zeny >= 4590) {
set zeny,zeny-4590;
@@ -9212,8 +9213,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 3:
if (Zeny >= 4590) {
set zeny,zeny-4590;
@@ -9222,8 +9223,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 4:
if (Zeny >= 4590) {
set zeny,zeny-4590;
@@ -9232,8 +9233,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 5:
if (Zeny >= 4590) {
set zeny,zeny-4590;
@@ -9242,8 +9243,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 6:
if (Zeny >= 4590) {
set zeny,zeny-4590;
@@ -9252,8 +9253,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 7:
if (Zeny >= 4590) {
set zeny,zeny-4590;
@@ -9262,8 +9263,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 8:
break;
}
@@ -9338,8 +9339,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 2:
if (Zeny >= 4590) {
set zeny,zeny-4590;
@@ -9348,8 +9349,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 3:
if (Zeny >= 4590) {
set zeny,zeny-4590;
@@ -9358,8 +9359,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 4:
if (Zeny >= 4590) {
set zeny,zeny-4590;
@@ -9368,8 +9369,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 5:
if (Zeny >= 4590) {
set zeny,zeny-4590;
@@ -9378,8 +9379,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 6:
if (Zeny >= 4590) {
set zeny,zeny-4590;
@@ -9388,8 +9389,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 7:
if (Zeny >= 4590) {
set zeny,zeny-4590;
@@ -9398,8 +9399,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 8:
break;
}
@@ -9414,8 +9415,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 2:
if (Zeny >= 4170) {
set zeny,zeny-4170;
@@ -9424,8 +9425,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 3:
if (Zeny >= 4170) {
set zeny,zeny-4170;
@@ -9434,8 +9435,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 4:
if (Zeny >= 4170) {
set zeny,zeny-4170;
@@ -9444,8 +9445,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 5:
if (Zeny >= 4170) {
set zeny,zeny-4170;
@@ -9454,8 +9455,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 6:
if (Zeny >= 4170) {
set zeny,zeny-4170;
@@ -9464,8 +9465,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 7:
if (Zeny >= 4170) {
set zeny,zeny-4170;
@@ -9474,8 +9475,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 8:
if (Zeny >= 4170) {
set zeny,zeny-4170;
@@ -9484,8 +9485,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 9:
break;
}
@@ -9500,8 +9501,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 2:
if (Zeny >= 4025) {
set zeny,zeny-4025;
@@ -9510,8 +9511,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 3:
if (Zeny >= 4025) {
set zeny,zeny-4025;
@@ -9520,8 +9521,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 4:
if (Zeny >= 4025) {
set zeny,zeny-4025;
@@ -9530,8 +9531,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 5:
if (Zeny >= 4025) {
set zeny,zeny-4025;
@@ -9540,8 +9541,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 6:
if (Zeny >= 4025) {
set zeny,zeny-4025;
@@ -9550,8 +9551,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 7:
if (Zeny >= 4025) {
set zeny,zeny-4025;
@@ -9560,8 +9561,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 8:
if (Zeny >= 4025) {
set zeny,zeny-4025;
@@ -9570,8 +9571,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 9:
if (Zeny >= 4025) {
set zeny,zeny-4025;
@@ -9580,8 +9581,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 10:
break;
}
@@ -9596,8 +9597,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 2:
if (Zeny >= 3970) {
set zeny,zeny-3970;
@@ -9606,8 +9607,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 3:
if (Zeny >= 3970) {
set zeny,zeny-3970;
@@ -9616,8 +9617,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 4:
if (Zeny >= 3970) {
set zeny,zeny-3970;
@@ -9626,8 +9627,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 5:
if (Zeny >= 3970) {
set zeny,zeny-3970;
@@ -9636,8 +9637,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 6:
if (Zeny >= 3970) {
set zeny,zeny-3970;
@@ -9646,8 +9647,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 7:
if (Zeny >= 3970) {
set zeny,zeny-3970;
@@ -9656,8 +9657,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 8:
if (Zeny >= 3970) {
set zeny,zeny-3970;
@@ -9666,8 +9667,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 9:
if (Zeny >= 3970) {
set zeny,zeny-3970;
@@ -9676,8 +9677,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 10:
if (Zeny >= 3970) {
set zeny,zeny-3970;
@@ -9686,8 +9687,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 11:
break;
}
@@ -9708,8 +9709,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 2:
if (Zeny >= 5500) {
set zeny,zeny-5500;
@@ -9718,8 +9719,8 @@ mid_camp,62,125,4 script Cat Hand Agent 421,{
else {
mes "[Cat Hand Agent]";
mes "Don't play with money.";
- close;
}
+ close;
case 3:
mes "[Cat Hand Agent]";
mes "Thank you for using our service.";
diff --git a/npc/quests/quests_lighthalzen.txt b/npc/quests/quests_lighthalzen.txt
index 27d9aa452..1917386cf 100644
--- a/npc/quests/quests_lighthalzen.txt
+++ b/npc/quests/quests_lighthalzen.txt
@@ -4,7 +4,7 @@
//= Persian, Vicious_Pucca, aoa00, Evera, MasterOfMupppets,
//= Lupus, Lord Gywall
//===== Current Version: =====================================
-//= 4.6
+//= 4.7
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -76,6 +76,7 @@
//= 4.5 Official Gangster Alert script. [Gepard]
//= 4.6 Added quest log entries for:
//= - Cursed Spirit Quest
+//= 4.7 Fixed missing label. (bugreport:4654) [L0ne_W0lf]
//============================================================
// Gangster Alert [Aegis Conversion]
@@ -5235,89 +5236,93 @@ lhz_in01,114,181,3 script Representative 71,{
mes "to the Rekenber Corporation.";
mes "How may I be of service today?";
next;
- if(lhz_curse == 7) menu "Building Information",L_Building,"Corporation History",L_History;
- else menu "Building Information",L_Building;
-
- while(1) {
- mes "[Representative]";
- mes "Please tell me";
- mes "which floor you'd like";
- mes "to know more about.";
- next;
- switch( select( "1F","2F","B1","Cancel" ) )
- {
- case 1:
- mes "[Representative]";
- mes "The ^3131FFRekenber Library^000000 can";
- mes "be found at the end of the";
- mes "left hallway. Our library is";
- mes "a great resource of innovative";
- mes "ideas and information for our";
- mes "system development employees.";
- next;
- mes "[Representative]";
- mes "The ^3131FFBall Room^000000, where";
- mes "various official events are";
- mes "usually held, can be accessed";
- mes "through the right hallway.";
- next;
- break;
+ if(lhz_curse == 7)
+ select("Building Information","Corporation History");
+ else
+ select("Building Information");
+
+ if (@menu == 1) {
+ while(1) {
+ mes "[Representative]";
+ mes "Please tell me";
+ mes "which floor you'd like";
+ mes "to know more about.";
+ next;
+ switch( select( "1F","2F","B1","Cancel" ) )
+ {
+ case 1:
+ mes "[Representative]";
+ mes "The ^3131FFRekenber Library^000000 can";
+ mes "be found at the end of the";
+ mes "left hallway. Our library is";
+ mes "a great resource of innovative";
+ mes "ideas and information for our";
+ mes "system development employees.";
+ next;
+ mes "[Representative]";
+ mes "The ^3131FFBall Room^000000, where";
+ mes "various official events are";
+ mes "usually held, can be accessed";
+ mes "through the right hallway.";
+ next;
+ break;
- case 2:
- mes "[Representative]";
- mes "Please use the stairs";
- mes "located on both sides of";
- mes "the Help Desk to go to the";
- mes "Second Floor. The Second";
- mes "Floor is mostly used for";
- mes "administrative purposes.";
- next;
- mes "[Representative]";
- mes "There, you can find";
- mes "the ^3131FFConference Room^000000,";
- mes "^3131FFSecretary Office^000000, the";
- mes "^3131FFAuditorium^000000 and the";
- mes "^3131FFChairman's Office^000000.";
- next;
- break;
+ case 2:
+ mes "[Representative]";
+ mes "Please use the stairs";
+ mes "located on both sides of";
+ mes "the Help Desk to go to the";
+ mes "Second Floor. The Second";
+ mes "Floor is mostly used for";
+ mes "administrative purposes.";
+ next;
+ mes "[Representative]";
+ mes "There, you can find";
+ mes "the ^3131FFConference Room^000000,";
+ mes "^3131FFSecretary Office^000000, the";
+ mes "^3131FFAuditorium^000000 and the";
+ mes "^3131FFChairman's Office^000000.";
+ next;
+ break;
- case 3:
- mes "[Representative]";
- mes "The first underground floor";
- mes "is used by the ^3131FFRegenshirm^000000,";
- mes "our laboratory affiliate. For";
- mes "security reasons, this floor";
- mes "is not accessible to visitors";
- next;
- break;
+ case 3:
+ mes "[Representative]";
+ mes "The first underground floor";
+ mes "is used by the ^3131FFRegenshirm^000000,";
+ mes "our laboratory affiliate. For";
+ mes "security reasons, this floor";
+ mes "is not accessible to visitors";
+ next;
+ break;
- case 4:
- mes "[Representative]";
- mes "We are always doing our";
- mes "best to provide the best";
- mes "services to our customers.";
- mes "Remember that Rekenber";
- mes "is the name you can trust.";
- mes "Thank you and have a nice day.";
- close;
+ case 4:
+ mes "[Representative]";
+ mes "We are always doing our";
+ mes "best to provide the best";
+ mes "services to our customers.";
+ mes "Remember that Rekenber";
+ mes "is the name you can trust.";
+ mes "Thank you and have a nice day.";
+ close;
+ }
}
}
-
-L_History:
- mes "[Representative]";
- mes "If you're interested in";
- mes "learning the history of";
- mes "our corporation, please";
- mes "speak to the representative";
- mes "inside our Library. Thank you.";
- next;
- mes "[Representative]";
- mes "Please head down";
- mes "the hallway to the left in";
- mes "order to find our Library.";
- mes "Thank you and have a nice day.";
- changequest 2087,2088;
- set lhz_curse,8;
+ else {
+ mes "[Representative]";
+ mes "If you're interested in";
+ mes "learning the history of";
+ mes "our corporation, please";
+ mes "speak to the representative";
+ mes "inside our Library. Thank you.";
+ next;
+ mes "[Representative]";
+ mes "Please head down";
+ mes "the hallway to the left in";
+ mes "order to find our Library.";
+ mes "Thank you and have a nice day.";
+ changequest 2087,2088;
+ set lhz_curse,8;
+ }
close;
}
diff --git a/npc/quests/quests_moscovia.txt b/npc/quests/quests_moscovia.txt
index 8371f59bd..89f642316 100644
--- a/npc/quests/quests_moscovia.txt
+++ b/npc/quests/quests_moscovia.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= Kisuka
//===== Current Version: =====================================
-//= 1.8
+//= 1.9
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -20,6 +20,7 @@
//= 1.6 Added 'tides' to Ibanoff & Fixed time check for Marozka. [Kisuka]
//= 1.7 Fixes on donpcevents and fixed some left over aegis stuff. [Kisuka]
//= 1.8 Fixed some condition checks. [Gepard]
+//= 1.9 Corrected NPC counting mobs for the wrong NPC. (bugreport:4736) [L0ne_W0lf]
//============================================================
//============================================================================
@@ -5117,7 +5118,7 @@ OnDisable:
end;
OnMyMobDead:
- if (mobcount("mosk_ship","Baehideun1#ship::OnMyMobDead") < 1) {
+ if (mobcount("mosk_ship","Baehideun4#ship::OnMyMobDead") < 1) {
set $@mos1_edq,0;
mes "[Mr. Ibanoff]";
mes "Now that all the monsters are gone,";
diff --git a/npc/quests/quests_veins.txt b/npc/quests/quests_veins.txt
index 8decb1264..a3647b34a 100644
--- a/npc/quests/quests_veins.txt
+++ b/npc/quests/quests_veins.txt
@@ -3,7 +3,7 @@
//===== By: ==================================================
//= L0ne_W0lf
//===== Current Version: =====================================
-//= 1.9
+//= 2.0
//===== Compatible With: =====================================
//= eAthena SVN
//===== Description: =========================================
@@ -43,6 +43,7 @@
//= 1.9 Added quest log entries for:
//= - Siblings Quest
//= - Thor Volcano Base Quest
+//= 2.0 Removed lvel requirement. (bugreport:4678) [L0ne_W0lf]
//============================================================
// Stone Quest
@@ -56,7 +57,7 @@ ve_fild05,257,130,4 script Wincing Old Man#ve 945,{
mes "- you put some items into Kafra Storage. -";
close;
}
- if ((veins_stone == 0) && (BaseLevel > 59)) {
+ if (veins_stone == 0) {
mes "[Zabaroo]";
mes "My back is killing me";
mes "after stooping over to";
@@ -300,11 +301,6 @@ ve_fild05,257,130,4 script Wincing Old Man#ve 945,{
mes "care of myself at my age...";
close;
}
- mes "[Zabaroo]";
- mes "I'm sorry dear.";
- mes "You're not strong enough for this kind of work.";
- mes "Put on some muscle and talk to me again.";
- close;
}
ve_in,169,310,6 script Strange Old Man#ve 121,{
diff --git a/npc/quests/skills/rogue_skills.txt b/npc/quests/skills/rogue_skills.txt
index 9d417cc1a..6c35b4102 100644
--- a/npc/quests/skills/rogue_skills.txt
+++ b/npc/quests/skills/rogue_skills.txt
@@ -237,9 +237,9 @@ in_rogue,355,179,0 script Haijara Greg#rogueguild 46,{
mes "[Haijara Greg]";
mes "Hmm... Well, I suppose";
if (Upper == 1)
- mes "I can trust a fellow Rogue";
- else
mes "I can trust a fellow Stalker";
+ else
+ mes "I can trust a fellow Rogue";
mes "with my predictament. Honor";
mes "among thieves and all that.";
mes "Alright. Have you ever heard";
diff --git a/readme.html b/readme.html
index 4fee74ee7..b133957f6 100644
--- a/readme.html
+++ b/readme.html
@@ -1,349 +1,40 @@
-<html><head><link rel="stylesheet" type="text/css" href="./readme/readme.css"><title>eAthena - Introduction</title></head>
-
-<body>
-<div id="dleftbg">
-</div>
-<div id="drightbg">
-</div>
-<div id="canvas" align="center">
-<table cellspacing="0" cellpadding="0" border="0" id="ea" align="center">
- <tr>
- <td id="leftborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="leftborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./readme/images/leftborder.gif">
- </td>
- </tr>
- </table>
- </td>
- <td id="middle" valign="top">
- <table cellspacing="0" cellpadding="0" border="0" valign="top">
- <tr>
- <td id="logo" valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td rowspan="4">
- <img src="./readme/images/chara.gif" width="366" height="274">
- </td>
- <td rowspan="4" width="129">
- </td>
- <td colspan="2" width="305" height="51" align="right">
- <img src="./readme/images/banner.gif" width="305" height="51">
- </td>
- </tr>
- <tr>
- <td id="title" colspan="2" align="right">
- Introduction
- </td>
- </tr>
- <tr>
- <td height="81" colspan="2">
- </td>
- </tr>
- <tr>
- <td class="navi" align="right">
- Introduction<br>
- <a href="./readme/changelog.html">Changelog</a><br>
- <a href="./readme/features.html">Features</a><br>
- <a href="./readme/npcfeatures.html">NPC Features</a>
-
- </td>
- <td class="navi" align="right">
- <a href="./readme/setup.html">Setup</a><br>
- <a href="./readme/gmcommands.html">GM Commands</a><br>
- <a href="./readme/faq.html">FAQ</a><br>
- <a href="./readme/resources.html">Resources</a>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="btmborder">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="2">
- <tr>
- <td id="leftbtmborder"">
- </td>
- <td id="midbtmborder"">
- <img src="./readme/images/btmborder.gif" width="44" height="2">
- </td>
- <td id="rightbtmborder">
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="content">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td id="lefttext" valign="top">
-<h1>eAthena SVN series</h1>
-eAthena is an open-source Ragnarok Online server emulator. It's written in C, but we are working on a C++ version. Although it is cross-platform, we only officially support Win32 and Linux.
-<br>
-<br>eAthena is licensed under the GPL, so please give us credit if you use our code.
-<br>Our SVN (<a href="http://tortoisesvn.tigris.org/download.html">You may download TortoiseSVN here to access our SVN</a>) is located at <a href="http://66.118.142.23:8080/svn/ea/">http://66.118.142.23:8080/svn/ea/</a>. SVN stands for Subversion, which is similar to the commonly used CVS.
-<br>
-<br>P.S. If you had a hard time loading this readme, please use <a href="http://www.getfirefox.com">Firefox</a>.
-
- </td>
- <td id="midtext">
- </td>
- <td id="righttext" valign="top">
-<h1>The eAthena Team</h1>
-Here are our current developers. We have had many past developers, and if you come across this, please let us know ^_^.<br>
-
-<b>Developers</b>
-<table class="right">
- <tr>
- <td>
- Wallex
- </td>
- <td>
- Lupus
- </td>
- <td>
- DracoRPG
- </td>
- </tr>
- <tr>
- <td>
- MasterOfMuppets
- </td>
-
- <td>
- Fredzilla
- </td>
- <td>
- Kayla
- </td>
- </tr>
- <tr>
- <td>
- Kevin
- </td>
- <td>
- Shinomori
- </td>
- <td>
- Clownphobia(Cuteboi)
- </td>
- </tr>
- <tr>
- <td>
- LuzZza
- </td>
- <td>
- Evera
- </td>
- <td>
- Nexon
- </td>
- </tr>
- <tr>
- <td>
- Celest
- </td>
- <td>
- Wizputer
- </td>
- <td>
- Valaris
- </td>
- </tr>
- <tr>
- <td>
- Lance
- </td>
- <td>
- Komurka
- </td>
- <td>
+<html>
+ <head>
+ <title>eAthena | Intro</title>
+ <link rel="stylesheet" type="text/css" href="./readme/style.css">
+ </head>
+ <body>
+ <div id="template">
+ <div id="header">
+ <div class="logo">eAthena<br /><span class="subtitle">- RAGNAROK Online Server Emulator</span></div>
+ <div class="title">Intro</div>
+ </div>
+ <div id="navcontainer">
+ <ul id="navlist">
+ <li><a href="./readme.html">Intro</a></li>
+ <li><a href="./readme/setup.html">Setup</a></li>
+ <li><a href="./readme/faq.html">FAQ</a></li>
+ <li><a href="./readme/scripting.html">Scripting</a></li>
+ <li><a href="./readme/commands.html">GM Commands</a></li>
+ <li><a href="./readme/resources.html">Resources</a></li>
+ </ul>
+ </div>
+
+ <div class="body-container">
+ <ul>
+ <li><span class="body-title">What is eAthena?</span><br>
+ eAthena is a collaborative software development project revolving around the creation of a robust massively multiplayer online role playing game (MMORPG) server package. Written in C, the program is very versatile and provides NPCs, warps and modifications. The project is jointly managed by a group of volunteers located around the world as well as a tremendous community providing QA and support. eAthena is a continuation of the original jAthena project.</li>
+ </ul>
+
+ <ul>
+ <li><span class="body-title">Who are the eAthena developers?</span><br>
+ You can find a list of the currently active eAthena developers at:<br>
+ <a href="http://code.google.com/p/eathena-project/people/list" target="_new">http://code.google.com/p/eathena-project/people/list</a>
+ </li>
+ </ul>
+ </div>
- </td>
- </tr>
-</table>
-<br>
-<b>Mods/Admins</b>
-<table class="right">
- <tr>
- <td>
- Massdriller
- </td>
- <td>
- Deviant
- </td>
- <td>
- Delta
- </td>
- </tr>
- <tr>
- <td>
- Manipulator
- </td>
- <td>
- SantaPoring
- </td>
- <td>
- Davidchak
- </td>
- </tr>
- <tr>
- <td>
- Valaris
- </td><td></td><td></td>
- </tr>
- <tr>
- <td>
- </td>
- </tr>
-</table>
-<br>
-<b>Ex-Developers and Honorable Mentions</b>
-<table class="right">
- <tr>
- <td>
- RoVeRT
- </td>
- <td>
- AppleGirl
- </td>
- <td>
- Akaru/Hikaru
- </td>
- </tr>
- <tr>
- <td>
- Darkchild
- </td>
- <td>
- Kalaspuff
- </td>
- <td>
- Ajarn
- </td>
- </tr>
- <tr>
- <td>
- Fritz
- </td>
- <td>
- Aria
- </td>
- <td>
- Mass Zero
- </td>
- </tr>
- <tr>
- <td>
- Nana
- </td>
- <td>
- Shinigami
- </td>
- <td>
- Moonsoul
- </td>
- </tr>
- <tr>
- <td>
- Kobra_k88
- </td>
- <td>
- Codemaster
- </td>
- <td>
- Davidsiaw
- </td>
- </tr>
- <tr>
- <td>
- MC_Cameri
- </td>
- <td>
- Spira
- </td>
- <td>
- Lord
- </td>
- </tr>
- <tr>
- <td>
- Yor
- </td>
- <td>
- Sara-chan
- </td>
- <td>
- Mikage
- </td>
- </tr>
- <tr>
- <td>
- Ajs15822
- </td>
- <td>
- Cyberghost
- </td>
- <td>
- Azndragon
- </td>
- </tr>
- <tr>
- <td>
- Nasedo
- </td>
- <td>
- Sirius
- </td>
- </tr>
-</table>
- <br />
- <br />
- </strong>
-
- </td>
- </tr>
- <tr>
- <td colspan="3">
- &copy; Content Copyright 2005 eAthena Development Team/Evera<br>
- &copy; Design Copyright 2005 Evera
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
-
-</table>
- <td id="rightborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="rightborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./readme/images/rightborder.gif">
- </td>
- </tr>
- </table>
- </td>
-</div>
- </td>
- </tr>
- </table>
- </td>
-
- </tr>
-</body>
-</html>
-
+ <div id="footer">"Read Me" Created & Designed by <a href="http://www.kisuka.com" target="_new">Kisuka</a></div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/readme/changelog.html b/readme/changelog.html
deleted file mode 100644
index ced251806..000000000
--- a/readme/changelog.html
+++ /dev/null
@@ -1,136 +0,0 @@
-<html><head><title>eAthena - Changelog</title><head>
-
-<link rel="stylesheet" type="text/css" href="./readme.css">
-
-<body>
-<div id="dleftbg">
-</div>
-<div id="drightbg">
-</div>
-<div id="canvas" align="center">
-<table cellspacing="0" cellpadding="0" border="0" id="ea" align="center">
- <tr>
- <td id="leftborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="leftborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/leftborder.gif">
- </td>
- </tr>
- </table>
- </td>
- <td id="middle" valign="top">
- <table cellspacing="0" cellpadding="0" border="0" valign="top">
- <tr>
- <td id="logo" valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td rowspan="4">
- <img src="./images/chara.gif" width="366" height="274">
- </td>
- <td rowspan="4" width="129">
- </td>
- <td colspan="2" width="305" height="51" align="right">
- <img src="./images/banner.gif" width="305" height="51">
- </td>
- </tr>
- <tr>
- <td id="title" colspan="2" align="right">
- Changelog
- </td>
- </tr>
- <tr>
- <td height="81" colspan="2">
- </td>
- </tr>
- <tr>
- <td class="navi" align="right">
- <a href="../readme.html">Introduction</a><br>
- Changelog<br>
- <a href="./features.html">Features</a><br>
- <a href="./npcfeatures.html">NPC Features</a>
-
- </td>
- <td class="navi" align="right">
- <a href="./setup.html">Setup</a><br>
- <a href="./gmcommands.html">GM Commands</a><br>
- <a href="./faq.html">FAQ</a><br>
- <a href="./resources.html">Resources</a>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="btmborder">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="2">
- <tr>
- <td id="leftbtmborder"">
- </td>
- <td id="midbtmborder"">
- <img src="./images/btmborder.gif" width="44" height="2">
- </td>
- <td id="rightbtmborder">
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="content">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td id="lefttext" valign="top">
-<h1>Changelog</h1>
-This is our current changelog. Please note this isn't our <i>complete</i> changelog.
-<br>
-
-
- </td>
- <td id="midtext">
- </td>
- <td id="righttext" valign="top">
- <iframe src="../Changelog-Trunk.txt" name="Changelog" title="eAthena SVN Changelog" marginwidth="10" marginheight="10" frameborder="0" height="500" width="100%"></iframe>
-
- </td>
- </tr>
- <tr>
- <td colspan="3">
- &copy; Content Copyright 2005 eAthena Development Team/Evera<br>
- &copy; Design Copyright 2005 Evera
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- <td id="rightborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="rightborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/rightborder.gif">
- </td>
- </tr>
- </table>
- </td>
-
- </tr>
-
-</table>
-</div>
-
diff --git a/readme/commands.html b/readme/commands.html
new file mode 100644
index 000000000..35d8bcf68
--- /dev/null
+++ b/readme/commands.html
@@ -0,0 +1,32 @@
+<html>
+ <head>
+ <title>eAthena | GM Commands</title>
+ <link rel="stylesheet" type="text/css" href="style.css">
+ </head>
+ <body>
+ <div id="template">
+ <div id="header">
+ <div class="logo">eAthena<br /><span class="subtitle">- RAGNAROK Online Server Emulator</span></div>
+ <div class="title">GM Commands</div>
+ </div>
+ <div id="navcontainer">
+ <ul id="navlist">
+ <li><a href="../readme.html">Intro</a></li>
+ <li><a href="setup.html">Setup</a></li>
+ <li><a href="faq.html">FAQ</a></li>
+ <li><a href="scripting.html">Scripting</a></li>
+ <li><a href="commands.html">GM Commands</a></li>
+ <li><a href="resources.html">Resources</a></li>
+ </ul>
+ </div>
+
+ <div class="body-container">
+ The following are the GM Commands which can be used in-game on an eAthena server.<br /><br />
+ <iframe width="100%" height="35%" src="../conf/help.txt"></iframe><br /><br />
+ <iframe width="100%" height="35%" src="../conf/help2.txt"></iframe>
+ </div>
+
+ <div id="footer">"Read Me" Created & Designed by <a href="http://www.kisuka.com" target="_new">Kisuka</a></div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/readme/faq-content.html b/readme/faq-content.html
new file mode 100644
index 000000000..9b12c674c
--- /dev/null
+++ b/readme/faq-content.html
@@ -0,0 +1,33 @@
+<html>
+<body>
+<ul>
+ <li><strong>Where can I set the exp rates?</strong><br />
+ - Go to /conf/battle/exp.conf<br />
+ - Find base_exp_rate and job_exp_rate. Change the value there to raise or lower the rates.<br />
+ - 100 = 1x, 1000 = 10x rates, etc<br />
+ <br />
+ </li>
+ <li><strong>Where can I set the item drop rates?</strong><br />
+ - Go to /conf/battle/drops.conf<br />
+ - You can set the drop rates by changing the values:<br />
+ item_rate_common: 100 &lt;-- 100 = 1x drop rate, 1000 = 10x drop rate, etc<br />
+ item_rate_common_boss: 100 &lt;--- drop rate for bosses<br />
+ item_drop_common_min: 1 &lt;--- minimal drop rate<br />
+ item_drop_common_max: 10000 &lt;--- maximum drop rate.<br />
+ (You can set the rates of different items in the same file)<br />
+ <br />
+ </li>
+ <li><strong>I found a bug, where to I report it?</strong><br />
+ If you find a bug in eAthena, report it here: <a href="http://www.eathena.ws/board/index.php?autocom=bugtracker" target="_blank">Bug Tracker</a><br />
+ <br />
+ </li>
+ <li><strong>I'm a well-experienced programmer, can I join the eAthena dev team?</strong><br />
+ Contact <a href="http://www.eathena.ws/board/index.php?showuser=121372" target="_blank">Paradox924X</a><br />
+ <br />
+ </li>
+ <li><strong>My character won't move, and no windows open when I login to the game, what's wrong?</strong><br />
+ Your packet_db_ver is most likely set wrong, change it in /db/packet_db.txt to match your client's packet ver.
+ </li>
+</ul>
+</body>
+</html> \ No newline at end of file
diff --git a/readme/faq.html b/readme/faq.html
index fc18e377c..0c5619830 100644
--- a/readme/faq.html
+++ b/readme/faq.html
@@ -1,151 +1,31 @@
-<html><head><title>eAthena - FAQ</title><head>
-
-<link rel="stylesheet" type="text/css" href="./readme.css">
-
-<body>
-<div id="dleftbg">
-</div>
-<div id="drightbg">
-</div>
-<div id="canvas" align="center">
-<table cellspacing="0" cellpadding="0" border="0" id="ea" align="center">
- <tr>
- <td id="leftborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="leftborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/leftborder.gif">
- </td>
- </tr>
- </table>
- </td>
- <td id="middle" valign="top">
- <table cellspacing="0" cellpadding="0" border="0" valign="top">
- <tr>
- <td id="logo" valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td rowspan="4">
- <img src="./images/chara.gif" width="366" height="274">
- </td>
- <td rowspan="4" width="129">
- </td>
- <td colspan="2" width="305" height="51" align="right">
- <img src="./images/banner.gif" width="305" height="51">
- </td>
- </tr>
- <tr>
- <td id="title" colspan="2" align="right">
- FAQ
- </td>
- </tr>
- <tr>
- <td height="81" colspan="2">
- </td>
- </tr>
- <tr>
- <td class="navi" align="right">
- <a href="../readme.html">Introduction</a><br>
- <a href="./changelog.html">Changelog</a><br>
- Features<br>
- <a href="./npcfeatures.html">NPC Features</a>
-
- </td>
- <td class="navi" align="right">
- <a href="./setup.html">Setup</a><br>
- <a href="./gmcommands.html">GM Commands</a><br>
- <a href="./faq.html">FAQ</a><br>
- <a href="./resources.html">Resources</a>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="btmborder">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="2">
- <tr>
- <td id="leftbtmborder"">
- </td>
- <td id="midbtmborder"">
- <img src="./images/btmborder.gif" width="44" height="2">
- </td>
- <td id="rightbtmborder">
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="content">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td id="lefttext" valign="top">
-<h1>FAQ</h1>
-<b>Q: I get the error message "This application has failed to start because cygwin1.dll was not found. Re-installing the application may fix this problem."</b><br>
- A: You're missing the cygwin dlls. Please get the latest dll at: http://www.cygwin.com/snapshot. If you're unsure, asking around in our IRC chatroom will get you around too, but always remember - use common sense and search before asking.<br><br>
-<b>Q: My map-server won't load! It appears to be loading things before it dissapeared suddenly! HELP!</b><br>
- A: Use command line to load map-server. It should tell you the error. If you're missing a map, update your kRO Sakray or comment the map from map_athena.conf. If you have an errornous NPC, fix it or comment it off. Anything other than that, feel free to ask around<br><br>
-<b>Q: My map-server failed to load 'adata.grf'! Where do I find this adata.grf? My map-server won't load without it!</b><br>
- A: The error that caused the map-server to not load is not the adata.grf. adata.grf is NOT a requirement for the map-server to load. The error is probably related to something else.<br><br>
- </td>
- <td id="midtext">
- </td>
- <td id="righttext" valign="top">
-<b>Q: All 3 of the servers are loaded, but I am still having problems accessing it! What do I do?</b><br>
- A: First, check the IPs in map_athena.conf and char_athena.conf. If those are correct, check the ports to make sure they match. If that's correct too, you probably cannot handle the server load. Lower the monster spawning rate using mob_count in battle_athena.conf and it should be fine.<br><br>
-<b>Q: How do I start Guild Wars/War of Emperium??? HELP!!!</b><br>
- A: Read the GM Command page for full list of commands that GMs can use, including the command for this.<br><br>
-<b>Q: My Ragnarok Online crashed while playing with eAthena! What do I do now?</b><br>
- A: Well, if your Ragnarok crashes, it's most probably not anything to do with eAthena. Something is wrong with your Ragnarok installation. Try reinstalling or updating.<br><br>
-<b>Q: Is eAthena compatible with mySQL? Can I use mySQL as the DB instead of using text files?</b><br>
- A: Yes, eAthena is compatible with mySQL. A tutorial on how to setup this is coming soon.<br><br>
-<b>Q: Is eAthena compatible with msSQL? Can I use msSQL as the DB instead of using text files?</b><br>
- A: No, eAthena is not compatible with msSQL. You cannot use msSQL with eAthena.<br><br>
-<b>Q: I found a bug! Where do I report it?</b><br>
- A: Drop the developers a line at the IRC chatroom. Or just post it in the bug report forum. We check them out too. :)<br><br>
-<b>Q: I know alot of C and I'm able to help improve eAthena and add new features. How can I join your development team?</b><br>
- A: Try talking to one of the current developers in the eAthena channel.
-
- </td>
- </tr>
- <tr>
- <td colspan="3">
- &copy; Content Copyright 2005 eAthena Development Team/Evera<br>
- &copy; Design Copyright 2005 Evera
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- <td id="rightborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="rightborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/rightborder.gif">
- </td>
- </tr>
- </table>
- </td>
-
- </tr>
-
-</table>
-</div>
-
+<html>
+ <head>
+ <title>eAthena | FAQ</title>
+ <link rel="stylesheet" type="text/css" href="style.css">
+ </head>
+ <body>
+ <div id="template">
+ <div id="header">
+ <div class="logo">eAthena<br /><span class="subtitle">- RAGNAROK Online Server Emulator</span></div>
+ <div class="title">FAQ</div>
+ </div>
+ <div id="navcontainer">
+ <ul id="navlist">
+ <li><a href="../readme.html">Intro</a></li>
+ <li><a href="setup.html">Setup</a></li>
+ <li><a href="faq.html">FAQ</a></li>
+ <li><a href="scripting.html">Scripting</a></li>
+ <li><a href="commands.html">GM Commands</a></li>
+ <li><a href="resources.html">Resources</a></li>
+ </ul>
+ </div>
+
+ <div class="body-container">
+ The following are frequently asked questions regarding eAthena.<br /><br />
+ <iframe width="100%" height="75%" src="faq-content.html"></iframe><br />
+ </div>
+
+ <div id="footer">"Read Me" Created & Designed by <a href="http://www.kisuka.com" target="_new">Kisuka</a></div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/readme/features.html b/readme/features.html
deleted file mode 100644
index 99b183c79..000000000
--- a/readme/features.html
+++ /dev/null
@@ -1,159 +0,0 @@
-<html><head><title>eAthena - Features</title><head>
-
-<link rel="stylesheet" type="text/css" href="./readme.css">
-
-<body>
-<div id="dleftbg">
-</div>
-<div id="drightbg">
-</div>
-<div id="canvas" align="center">
-<table cellspacing="0" cellpadding="0" border="0" id="ea" align="center">
- <tr>
- <td id="leftborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="leftborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/leftborder.gif">
- </td>
- </tr>
- </table>
- </td>
- <td id="middle" valign="top">
- <table cellspacing="0" cellpadding="0" border="0" valign="top">
- <tr>
- <td id="logo" valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td rowspan="4">
- <img src="./images/chara.gif" width="366" height="274">
- </td>
- <td rowspan="4" width="129">
- </td>
- <td colspan="2" width="305" height="51" align="right">
- <img src="./images/banner.gif" width="305" height="51">
- </td>
- </tr>
- <tr>
- <td id="title" colspan="2" align="right">
- Features
- </td>
- </tr>
- <tr>
- <td height="81" colspan="2">
- </td>
- </tr>
- <tr>
- <td class="navi" align="right">
- <a href="../readme.html">Introduction</a><br>
- <a href="./changelog.html">Changelog</a><br>
- Features<br>
- <a href="./npcfeatures.html">NPC Features</a>
-
- </td>
- <td class="navi" align="right">
- <a href="./setup.html">Setup</a><br>
- <a href="./gmcommands.html">GM Commands</a><br>
- <a href="./faq.html">FAQ</a><br>
- <a href="./resources.html">Resources</a>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="btmborder">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="2">
- <tr>
- <td id="leftbtmborder"">
- </td>
- <td id="midbtmborder"">
- <img src="./images/btmborder.gif" width="44" height="2">
- </td>
- <td id="rightbtmborder">
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="content">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td id="lefttext" valign="top">
-<h1>Features</h1>
-eAthena tries to keep up with kRO (Korean Ragnarok Online, an official server) in terms of features. Many of the features we have
-are re-coded versions of official onces. We also have many eAthena exclusive features, such as various NPC commands. We also
-have all of the RO server emu goodies, like open-source modification and custom sprites/items. We are currently on <i>feature-lock</i>,
-so we will focus mainly on stability for the time being, not new features.
-
-
- </td>
- <td id="midtext">
- </td>
- <td id="righttext" valign="top">
-<ul>
- <li>PVP (Player Vs. Player)</li>
- <li>Adoption System</li>
- <li>Dynamic monster spawning system</li>
- <li>GVG (Guild Vs. Guild)</li>
- <li>qPets (Cute Pets)</li>
- <li>Monster Skills</li>
- <li>2-2 Jobs (Alternate 2nd Jobs)</li>
- <li>Super Novice (Alternate 1st Job)</li>
- <li>WoE (War of Emperium)</li>
- <li>Weddings</li>
- <li>Pet equipped mobs</li>
- <li>Management of day/night</li>
- <li>Mob Disguises</li>
- <li>Weather and other special effects</li>
- <li>"Rebirth/Transcendent" Classes</li>
- <li>Room for custom sprites/items</li>
- <li>Open source, allowing for your own personal modifications</li>
- <li>Two different storage systems, TXT and SQL</li>
- <li>Stability</li>
- <li>Many other various features</li>
-</ul>
-
- </td>
- </tr>
- <tr>
- <td colspan="3">
- &copy; Content Copyright 2005 eAthena Development Team/Evera<br>
- &copy; Design Copyright 2005 Evera
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- <td id="rightborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="rightborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/rightborder.gif">
- </td>
- </tr>
- </table>
- </td>
-
- </tr>
-
-</table>
-</div>
-
diff --git a/readme/gmcommands.html b/readme/gmcommands.html
deleted file mode 100644
index 255240d00..000000000
--- a/readme/gmcommands.html
+++ /dev/null
@@ -1,139 +0,0 @@
-<html><head><title>eAthena - GM Commands</title><head>
-
-<link rel="stylesheet" type="text/css" href="./readme.css">
-
-<body>
-<div id="dleftbg">
-</div>
-<div id="drightbg">
-</div>
-<div id="canvas" align="center">
-<table cellspacing="0" cellpadding="0" border="0" id="ea" align="center">
- <tr>
- <td id="leftborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="leftborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/leftborder.gif">
- </td>
- </tr>
- </table>
- </td>
- <td id="middle" valign="top">
- <table cellspacing="0" cellpadding="0" border="0" valign="top">
- <tr>
- <td id="logo" valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td rowspan="4">
- <img src="./images/chara.gif" width="366" height="274">
- </td>
- <td rowspan="4" width="129">
- </td>
- <td colspan="2" width="305" height="51" align="right">
- <img src="./images/banner.gif" width="305" height="51">
- </td>
- </tr>
- <tr>
- <td id="title" colspan="2" align="right">
- GM Commands
- </td>
- </tr>
- <tr>
- <td height="81" colspan="2">
- </td>
- </tr>
- <tr>
- <td class="navi" align="right">
- <a href="../readme.html">Introduction</a><br>
- <a href="./changelog.html">Changelog</a><br>
- <a href="./features.html">Features</a><br>
- <a href="./npcfeatures.html">NPC Features</a>
-
- </td>
- <td class="navi" align="right">
- <a href="./setup.html">Setup</a><br>
- GM Commands<br>
- <a href="./faq.html">FAQ</a><br>
- <a href="./resources.html">Resources</a>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="btmborder">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="2">
- <tr>
- <td id="leftbtmborder"">
- </td>
- <td id="midbtmborder"">
- <img src="./images/btmborder.gif" width="44" height="2">
- </td>
- <td id="rightbtmborder">
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="content">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td id="lefttext" valign="top">
-<h1>GM Commands</h1>
-A GM, or Game Master, on eAthena has access to certain codes to administer the server. A GM is appointed by the server owner, and can not
-be gained normally through the game. These commands start with the @ symbol, a well-recognized sign of an Athena server. Many of our current
-commands are broken and don't work properly.
- </td>
- <td id="midtext">
- </td>
- <td id="righttext" valign="top">
-<iframe src="../conf/help.txt" name="Help" title="eAthena Gm Commands" marginwidth="10" marginheight="10" frameborder="0" height="500" width="100%"></iframe>
-
-
-
-
-
- </td>
- </tr>
- <tr>
- <td colspan="3">
- &copy; Content Copyright 2005 eAthena Development Team/Evera<br>
- &copy; Design Copyright 2005 Evera
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- <td id="rightborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="rightborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/rightborder.gif">
- </td>
- </tr>
- </table>
- </td>
-
- </tr>
-
-</table>
-</div>
-
diff --git a/readme/images/banner.gif b/readme/images/banner.gif
deleted file mode 100644
index b11ea7dd9..000000000
--- a/readme/images/banner.gif
+++ /dev/null
Binary files differ
diff --git a/readme/images/bg.gif b/readme/images/bg.gif
index 20b046176..6c8c92c3b 100644
--- a/readme/images/bg.gif
+++ b/readme/images/bg.gif
Binary files differ
diff --git a/readme/images/btmborder.gif b/readme/images/btmborder.gif
deleted file mode 100644
index 116e49bb3..000000000
--- a/readme/images/btmborder.gif
+++ /dev/null
Binary files differ
diff --git a/readme/images/btmborderbg.gif b/readme/images/btmborderbg.gif
deleted file mode 100644
index 82a27195f..000000000
--- a/readme/images/btmborderbg.gif
+++ /dev/null
Binary files differ
diff --git a/readme/images/chara.gif b/readme/images/chara.gif
deleted file mode 100644
index 13b118a7a..000000000
--- a/readme/images/chara.gif
+++ /dev/null
Binary files differ
diff --git a/readme/images/clown.png b/readme/images/clown.png
new file mode 100644
index 000000000..55de4ba60
--- /dev/null
+++ b/readme/images/clown.png
Binary files differ
diff --git a/readme/images/leftbg.gif b/readme/images/leftbg.gif
deleted file mode 100644
index 0d4322919..000000000
--- a/readme/images/leftbg.gif
+++ /dev/null
Binary files differ
diff --git a/readme/images/leftborder.gif b/readme/images/leftborder.gif
deleted file mode 100644
index c139a9a5f..000000000
--- a/readme/images/leftborder.gif
+++ /dev/null
Binary files differ
diff --git a/readme/images/logo.gif b/readme/images/logo.gif
deleted file mode 100644
index 4f01126ec..000000000
--- a/readme/images/logo.gif
+++ /dev/null
Binary files differ
diff --git a/readme/images/logobtm.gif b/readme/images/logobtm.gif
deleted file mode 100644
index a80f6bc67..000000000
--- a/readme/images/logobtm.gif
+++ /dev/null
Binary files differ
diff --git a/readme/images/rightbg.gif b/readme/images/rightbg.gif
deleted file mode 100644
index bd5825593..000000000
--- a/readme/images/rightbg.gif
+++ /dev/null
Binary files differ
diff --git a/readme/images/rightborder.gif b/readme/images/rightborder.gif
deleted file mode 100644
index 88e27d304..000000000
--- a/readme/images/rightborder.gif
+++ /dev/null
Binary files differ
diff --git a/readme/images/textbg.gif b/readme/images/textbg.gif
deleted file mode 100644
index a092b75c1..000000000
--- a/readme/images/textbg.gif
+++ /dev/null
Binary files differ
diff --git a/readme/npcfeatures.html b/readme/npcfeatures.html
deleted file mode 100644
index 67b816b87..000000000
--- a/readme/npcfeatures.html
+++ /dev/null
@@ -1,262 +0,0 @@
-<html><head><title>eAthena - NPC Features</title><head>
-
-<link rel="stylesheet" type="text/css" href="./readme.css">
-
-<body>
-<div id="dleftbg">
-</div>
-<div id="drightbg">
-</div>
-<div id="canvas" align="center">
-<table cellspacing="0" cellpadding="0" border="0" id="ea" align="center">
- <tr>
- <td id="leftborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="leftborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/leftborder.gif">
- </td>
- </tr>
- </table>
- </td>
- <td id="middle" valign="top">
- <table cellspacing="0" cellpadding="0" border="0" valign="top">
- <tr>
- <td id="logo" valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td rowspan="4">
- <img src="./images/chara.gif" width="366" height="274">
- </td>
- <td rowspan="4" width="129">
- </td>
- <td colspan="2" width="305" height="51" align="right">
- <img src="./images/banner.gif" width="305" height="51">
- </td>
- </tr>
- <tr>
- <td id="title" colspan="2" align="right">
- NPC Features
- </td>
- </tr>
- <tr>
- <td height="81" colspan="2">
- </td>
- </tr>
- <tr>
- <td class="navi" align="right">
- <a href="../readme.html">Introduction</a><br>
- <a href="./changelog.html">Changelog</a><br>
- <a href="./features.html">Features</a><br>
- NPC Features
-
- </td>
- <td class="navi" align="right">
- <a href="./setup.html">Setup</a><br>
- <a href="./gmcommands.html">GM Commands</a><br>
- <a href="./faq.html">FAQ</a><br>
- <a href="./resources.html">Resources</a>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="btmborder">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="2">
- <tr>
- <td id="leftbtmborder"">
- </td>
- <td id="midbtmborder"">
- <img src="./images/btmborder.gif" width="44" height="2">
- </td>
- <td id="rightbtmborder">
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="content">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td id="lefttext" valign="top">
-<h1>NPC Features</h1>
-One of the best aspects of eAthena is the NPC system. As a base, we have most of the official kRO NPC scripts, and if they are in
-iRO, we have their correct translations. You can put any of your custom NPCs on top of these, using our extremely easy-to-learn
-scripting language. We also have a wide variety of custom NPCs available in /npc/custom/ and for download in the forums to
-maximize your players' experiences.
-
-
- </td>
- <td id="midtext">
- </td>
- <td id="righttext" valign="top">
- <ul>
- <li><strong>Town Npcs</strong> (11/17)</li>
- <ul><li>&nbsp;Alberta - 100%</li></ul>
- <ul><li>&nbsp;Al de Baran - 100%</li></ul>
- <ul><li>&nbsp;Amatsu - 100%</li></ul>
- <ul><li>&nbsp;Ayothaya - 75%</li></ul>
- <ul><li>&nbsp;Comodo - 100%</li></ul>
- <ul><li>&nbsp;Einbech - 90%</li></ul>
- <ul><li>&nbsp;Einbroch - 75%</li></ul>
- <ul><li>&nbsp;Geffen - 100%</li></ul>
- <ul><li>&nbsp;Gonryun - 60%</li></ul>
- <ul><li>&nbsp;Izlude - 100%</li></ul>
- <ul><li>&nbsp;Louyang - 75%</li></ul>
- <ul><li>&nbsp;Lutie - 100%</li></ul>
- <ul><li>&nbsp;Morocc - 100%</li></ul>
- <ul><li>&nbsp;Niflheim - 100%</li></ul>
- <ul><li>&nbsp;Payon(New Maps) - 99%</li></ul>
- <ul><li>&nbsp;Prontera - 100%</li></ul>
- <ul><li>&nbsp;Umbala - 100%</li></ul>
-
- <li><strong>Job Quests</strong> (16/33)</li>
- <ul><li>&nbsp;Novice Class (2/2)</li></ul>
- <ul><ul><li>&nbsp;Novice - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Super Novice - 100%</li></ul></ul>
- <ul><li>&nbsp;1-1 Class (6/6)</li></ul>
- <ul><ul><li>&nbsp;Swordman - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Mage - 100%</li></ul></ul>
-
-
- <ul><ul><li>&nbsp;Archer - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Acolyte - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Merchant - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Thief - 100%</li></ul></ul>
- <ul><li>&nbsp;2-1 Class (6/6)</li></ul>
- <ul><ul><li>&nbsp;Knight - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Priest - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Wizard - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Blacksmith - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Hunter - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Assassin - 100%</li></ul></ul>
-
- <ul><li>&nbsp;2-2 Class (2/7)</li></ul>
- <ul><ul><li>&nbsp;Crusader - 0%</li></ul></ul>
- <ul><ul><li>&nbsp;Monk - 0% (Soon)</li></ul></ul>
- <ul><ul><li>&nbsp;Sage - 0% (Soon)</li></ul></ul>
- <ul><ul><li>&nbsp;Rogue - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Alchemist - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Bard - 0%</li></ul></ul>
- <ul><ul><li>&nbsp;Dancer - 100%</li></ul></ul>
-
- <ul><li>&nbsp;2-1-1 Class (0/6)</li></ul>
- <ul><li>&nbsp;2-2-1 Class (0/6)</li></ul>
- <li><strong>Kafras</strong> - 100%</li>
-
- <li><strong>Guides</strong> - 100%</li>
-
- <li>&nbsp;<strong>War Of Emperium</strong> (4/5)</li>
- <ul><li>&nbsp;Prontera - 100%</li></ul>
- <ul><li>&nbsp;Geffen - 100%</li></ul>
-
- <ul><li>&nbsp;Payon - 100%</li></ul>
- <ul><li>&nbsp;Al De Baran - 100%</li></ul>
-
- <ul><li>&nbsp;Novice - 0%</li></ul>
- <li><strong>Quests</strong> (24/25)</li>
-
- <ul><li>&nbsp;Skill Quests (7/7)</li></ul>
-
- <ul><ul><li>&nbsp;Novice - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Swordman - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Mage - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Archer - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Acolyte - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Merchant - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Thief - 100%</li></ul></ul>
-
- <ul><li>Town Quests (9/10)</li></ul>
- <ul><ul><li>&nbsp;Prontera - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Morocc - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Geffen - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Izlude - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Alberta - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Al De Baran - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Yuno - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Lutie - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Comodo - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Payon - 20%</li></ul></ul>
- <ul><li>Other Quests (9/9)</li></ul>
- <ul><ul><li>&nbsp;Dye - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;MrSmile - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Juice Making - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Doomed Swords - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Bongun Taming - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Munak Taming - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Tamking - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Bongun Sword - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;The lvl 4 Weapon Quest - 100%</li></ul></ul>
- <ul><li>Other (7/10)</li></ul>
- <ul><ul><li>&nbsp;Card Remover - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;PvP (old) - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Time Arena - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Bank - 100%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Wedding - 80%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Valkyrie - 10%</li></ul></ul>
-
- <ul><ul><li>&nbsp;Gefenia - 10%</li></ul></ul>
- <ul><ul><li>&nbsp;Heal Npc - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Warp Npc - 100%</li></ul></ul>
- <ul><ul><li>&nbsp;Jobchange - 100%</li></ul></ul>
- </ul>
-
- </td>
- </tr>
- <tr>
- <td colspan="3">
- &copy; Content Copyright 2005 eAthena Development Team/Evera<br>
- &copy; Design Copyright 2005 Evera
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- <td id="rightborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="rightborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/rightborder.gif">
- </td>
- </tr>
- </table>
- </td>
-
- </tr>
-
-</table>
-</div>
-
diff --git a/readme/readme.css b/readme/readme.css
deleted file mode 100644
index 63742c60c..000000000
--- a/readme/readme.css
+++ /dev/null
@@ -1,227 +0,0 @@
-/* Go away, Troll */
-
-A,
-A:link,
-A:visited,
-A:active,
-A:hover {
-
-color: #000;
-
-text-decoration: underline;
-
-background-color : inherit;
-
-}
-
-
-html {
-
- margin: 0px;
-
- padding: 0px;
-
-}
-
-body {
-
- background: url(./images/bg.gif);
-
- margin: 0px 0px 0px 0px;
-
- padding: 0px 0px 0px 0px;
-
- font: 14px Arial, arial;
-
- color: #000;
-
-}
-
-h1 {
-
- width : 100%;
-
- height : 40px;
-
- text-align : bottom;
-
- font : 30px Arial Black, arial black, helvetica, sans-serif;
-
-}
-
-.w800 {
-
- width: 800px;
-
-}
-
-#dleftbg,
-#drightbg {
-
- position: absolute;
-
- width: 50%;
-
- overflow: hidden;
-
- height: 69px;
-
- z-index: 0;
-
-}
-
-#dleftbg {
-
- top: 66px;
-
- left: 0px;
-
- background: url(./images/leftbg.gif);
-
-}
-
-#drightbg {
-
- top: 105px;
-
- right: 0px;
-
- background: url(./images/rightbg.gif);
-
-}
-
-#canvas {
-
- position: absolute;
-
- z-index: 1;
-
- width: 100%;
-
- height: 100%;
-
-}
-
-#ea {
-
- height: 100%;
-
-}
-
-
-#leftborderspacer,
-#leftbgspacer {
-
- height: 66px;
-
-}
-
-#rightborderspacer {
-
- height: 106px;
-
-}
-
-
-#leftborder,
-#rightborder {
-
- background: #000;
-
- width: 1px;
-
-}
-
-.vspacer {
-
-
-
-}
-
-#middle {
-
- background: url(./images/textbg.gif);
-
- width: 800px;
-
- height: 100%;
-
-}
-
-#logo {
-
- background: url(./images/logo.gif) no-repeat top left;
-
- height: 100%;
-
-}
-
-#title {
-
- font : 30px Arial Black, arial black, helvetica, sans-serif;
-
- height: 54px;
-
-}
-
-.navi {
-
- font : 14px Arial Black, arial black, helvetica, sans-serif;
-
- height: 88px;
-
-}
-
-#btmborder {
-
- background: url(./images/btmborderbg.gif);
-
- height: 2px;
-
-}
-
-.left,
-#lefttext,
-#leftbtmborder {
-
- width: 327px;
-
-}
-
-#midtext,
-#midbtmborder {
-
- width: 44px;
-
-}
-
-.right,
-#righttext,
-#rightbtmborder {
-
- width: 429px;
-
-}
-
-#content {
-
- height: 100px;
-
-}
-
-#lefttext,
-#righttext {
-
- background: url(./images/textbg.gif);
-
- height: 100%;
-
-}
-
-#midtext {
-
- background: url(./images/logobtm.gif);
-
- height: 100%;
-
-} \ No newline at end of file
diff --git a/readme/resources.html b/readme/resources.html
index 7a3f71ee3..87947b80d 100644
--- a/readme/resources.html
+++ b/readme/resources.html
@@ -1,150 +1,67 @@
-<html><head><title>eAthena - Resources</title><head>
-
-<link rel="stylesheet" type="text/css" href="./readme.css">
-
-<body>
-<div id="dleftbg">
-</div>
-<div id="drightbg">
-</div>
-<div id="canvas" align="center">
-<table cellspacing="0" cellpadding="0" border="0" id="ea" align="center">
- <tr>
- <td id="leftborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="leftborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/leftborder.gif">
- </td>
- </tr>
- </table>
- </td>
- <td id="middle" valign="top">
- <table cellspacing="0" cellpadding="0" border="0" valign="top">
- <tr>
- <td id="logo" valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td rowspan="4">
- <img src="./images/chara.gif" width="366" height="274">
- </td>
- <td rowspan="4" width="129">
- </td>
- <td colspan="2" width="305" height="51" align="right">
- <img src="./images/banner.gif" width="305" height="51">
- </td>
- </tr>
- <tr>
- <td id="title" colspan="2" align="right">
- Resources
- </td>
- </tr>
- <tr>
- <td height="81" colspan="2">
- </td>
- </tr>
- <tr>
- <td class="navi" align="right">
- <a href="../readme.html">Introduction</a><br>
- <a href="./changelog.html">Changelog</a><br>
- <a href="./features.html">Features</a><br>
- <a href="./npcfeatures.html">NPC Features</a>
-
- </td>
- <td class="navi" align="right">
- <a href="./setup.html">Setup</a><br>
- <a href="./gmcommands.html">GM Commands</a><br>
- <a href="./faq.html">FAQ</a><br>
- Resources
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="btmborder">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="2">
- <tr>
- <td id="leftbtmborder"">
- </td>
- <td id="midbtmborder"">
- <img src="./images/btmborder.gif" width="44" height="2">
- </td>
- <td id="rightbtmborder">
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="content">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td id="lefttext" valign="top">
-<h1>Official Sources</h1>
-<b><a href="http://www.eathena.ws">http://www.eathena.ws</a></b>
- Our Official Webpage.<br>
-<b><a href="http://forum.asb-sakray.net">http://forum.asb-sakray.net</a></b>
- Aegis Support Board.<br>
-Please take note, you are adviced to search in the forums
-first before requesting for help to be made toward you.<br>
-<br>
-<b>IRC Channel:</b><br>
-
-<b><a href="irc://irc.deltaanime.net">irc.deltaanime.net</a></b>
- #athena (Please make sure to check both forums before coming into
- the channel to ask questions, or else we will not only ignore you,
- but laugh at you too.)
- </td>
- <td id="midtext">
- </td>
- <td id="righttext" valign="top">
-<h1>Other Sources</h1>
-<b><a href="http://kalen.s79.xrea.com/npc/">http://kalen.s79.xrea.com/npc/</a></b>
- NPC Factory (Lists NPC/number)<br>
-<br>
-If you want your site to be featured here, please tell a dev ^_^.
-
-
- </td>
- </tr>
- <tr>
- <td colspan="3">
- &copy; Content Copyright 2005 eAthena Development Team/Evera<br>
- &copy; Design Copyright 2005 Evera
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- <td id="rightborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="rightborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/rightborder.gif">
- </td>
- </tr>
- </table>
- </td>
-
- </tr>
-
-</table>
-</div>
-
+<html>
+ <head>
+ <title>eAthena | Resources</title>
+ <link rel="stylesheet" type="text/css" href="style.css">
+ </head>
+ <body>
+ <div id="template">
+ <div id="header">
+ <div class="logo">eAthena<br /><span class="subtitle">- RAGNAROK Online Server Emulator</span></div>
+ <div class="title">Resources</div>
+ </div>
+ <div id="navcontainer">
+ <ul id="navlist">
+ <li><a href="../readme.html">Intro</a></li>
+ <li><a href="setup.html">Setup</a></li>
+ <li><a href="faq.html">FAQ</a></li>
+ <li><a href="scripting.html">Scripting</a></li>
+ <li><a href="commands.html">GM Commands</a></li>
+ <li><a href="resources.html">Resources</a></li>
+ </ul>
+ </div>
+
+ <div class="body-container">
+ The following are some links to various resources which can be helpful when using eAthena.<br />
+ <ul>
+ <li><a href="http://www.eathena.ws/" target="_new">http://www.eathena.ws/</a><br>
+ The official eAthena project website.
+ </li><br>
+
+ <li><a href="http://eathena-project.googlecode.com/svn/" target="_new">
+ http://eathena-project.googlecode.com/svn/</a><br>
+ The official SVN of the eAthena project.</li><br>
+
+ <li><a href="irc://irc.deltaanime.net/#athena" target="_new">irc://irc.deltaanime.net/#athena</a><br>
+ The official eAthena IRC Channel.</li><br>
+
+ <li><a href="http://forum.asb-sakray.net/" target="_new">http://forum.asb-sakray.net/</a><br>
+ The official AEGIS Support Board.</li><br>
+
+ <li><a href="http://www.ragnarokonline.com/" target="_new">
+ http://www.ragnarokonline.com/</a><br>
+ The official Ragnarok Online website.
+ </li><br>
+
+ <li><a href="http://nn.nachtwolke.com/dev/npclist/" target="_new">
+ http://nn.nachtwolke.com/dev/npclist/</a><br>
+ List of Ragnarok Online NPC sprite names and IDs.
+ </li><br>
+
+ <li><a href="../doc/script_commands.txt" target="_new">Script Commands</a><br>
+ Documentation of the script commands available in eAthena.
+ </li><br>
+
+ <li><a href="../doc/effect_list.txt" target="_new">Effect List</a><br>
+ Documentation of the visual effects available in eAthena.
+ </li><br>
+
+ <li><a href="../doc/item_bonus.txt" target="_new">Item Bonuses</a><br>
+ Documentation of the item bonuses available in eAthena.
+ </li><br>
+ </ul>
+ </div>
+
+ <div id="footer">"Read Me" Created & Designed by <a href="http://www.kisuka.com" target="_new">Kisuka</a></div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/readme/scripting.html b/readme/scripting.html
new file mode 100644
index 000000000..e01894e65
--- /dev/null
+++ b/readme/scripting.html
@@ -0,0 +1,69 @@
+<html>
+ <head>
+ <title>eAthena | Scripting</title>
+ <link rel="stylesheet" type="text/css" href="style.css">
+ </head>
+<body>
+ <div id="template">
+ <div id="header">
+ <div class="logo">eAthena<br /><span class="subtitle">- RAGNAROK Online Server Emulator</span></div>
+ <div class="title">Scripting</div>
+ </div>
+ <div id="navcontainer">
+ <ul id="navlist">
+ <li><a href="../readme.html">Intro</a></li>
+ <li><a href="setup.html">Setup</a></li>
+ <li><a href="faq.html">FAQ</a></li>
+ <li><a href="scripting.html">Scripting</a></li>
+ <li><a href="commands.html">GM Commands</a></li>
+ <li><a href="resources.html">Resources</a></li>
+ </ul>
+ </div>
+
+ <div class="body-container">
+ <p>
+ How to create an NPC using eAthena's scripting:<br /><br />
+ <font color="#0000FF">map_name</font>,<font color="#009900">x_cord</font>,<font color="#0CF305">y_cord</font>,<font color="#FF0000">npc_facing_direction</font> <strong>-TAB-</strong> script <strong>-TAB-</strong> <font color="#FF6600">NPC Name</font>#<font color="#FFCC00">HiddenName</font> <strong>-TAB-</strong> <font color="#CC3399">Sprite ID</font>,{<br />
+ &nbsp;&nbsp;&nbsp;mes "[NPC Name]";<br>
+ &nbsp;&nbsp;&nbsp;mes "Hello World";<br>
+ &nbsp;&nbsp;&nbsp;close;<br>
+ }
+ </p>
+ <p>
+ <strong>Common Script Commands:</strong>
+ <ul>
+ <li><strong>mes</strong><br>
+ usage: mes &quot;&lt;message&gt;&quot;;<br>
+ info: displays a line of text in an NPC's dialog window.</li>
+ <li><strong>close</strong><br>
+ usage: close;<br>
+ info: displays a &quot;Close&quot; button in an NPC's dialog window.
+ </li>
+ <li><strong>next</strong><br>
+ usage: next;<br>
+ info: displays a &quot;Next&quot; button in an NPC's dialog window.</li>
+ <li><strong>getitem</strong><br>
+ usage: getitem &lt;item id&gt;,&lt;amount&gt;;<br>
+ info: gives the player an item.
+ </li>
+ <li><strong>delitem</strong><br>
+ usage: delitem &lt;item id&gt;,&lt;amount&gt;;<br>
+ info: deletes an item from the player.
+ </li>
+ </ul>
+ <p><strong>Script Command Documentation:</strong><br>
+
+ All the script commands in eAthena can be found <a href="../doc/script_commands.txt" target="_new">here</a>.</p>
+ <p><strong>How to enable your NPC:</strong><br>
+ 1. Save it as a text file in your /npc/custom/ folder.<br>
+ 2. Open /npc/scripts_custom.conf<br>
+ 3. Add the following line:<br>
+ <em>npc: npc/custom/name_of_your_text_file.txt</em><br>
+ 4. Save and close.</p>
+ </p>
+ </div>
+
+ <div id="footer">"Read Me" Created & Designed by <a href="http://www.kisuka.com" target="_new">Kisuka</a></div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/readme/setup.html b/readme/setup.html
index c4463ef89..7f91852b8 100644
--- a/readme/setup.html
+++ b/readme/setup.html
@@ -1,144 +1,62 @@
-<html><head><title>eAthena - Setup</title><head>
-
-<link rel="stylesheet" type="text/css" href="./readme.css">
-
-<body>
-<div id="dleftbg">
-</div>
-<div id="drightbg">
-</div>
-<div id="canvas" align="center">
-<table cellspacing="0" cellpadding="0" border="0" id="ea" align="center">
- <tr>
- <td id="leftborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="leftborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/leftborder.gif">
- </td>
- </tr>
- </table>
- </td>
- <td id="middle" valign="top">
- <table cellspacing="0" cellpadding="0" border="0" valign="top">
- <tr>
- <td id="logo" valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td valign="top">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td rowspan="4">
- <img src="./images/chara.gif" width="366" height="274">
- </td>
- <td rowspan="4" width="129">
- </td>
- <td colspan="2" width="305" height="51" align="right">
- <img src="./images/banner.gif" width="305" height="51">
- </td>
- </tr>
- <tr>
- <td id="title" colspan="2" align="right">
- Setup
- </td>
- </tr>
- <tr>
- <td height="81" colspan="2">
- </td>
- </tr>
- <tr>
- <td class="navi" align="right">
- <a href="../readme.html">Introduction</a><br>
- <a href="./changelog.html">Changelog</a><br>
- <a href="./features.html">Features</a><br>
- <a href="./npcfeatures.html">NPC Features</a>
-
- </td>
- <td class="navi" align="right">
- Setup<br>
- <a href="./gmcommands.html">GM Commands</a><br>
- <a href="./faq.html">FAQ</a><br>
- <a href="./resources.html">Resources</a>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="btmborder">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="2">
- <tr>
- <td id="leftbtmborder"">
- </td>
- <td id="midbtmborder"">
- <img src="./images/btmborder.gif" width="44" height="2">
- </td>
- <td id="rightbtmborder">
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td id="content">
- <table class="w800" cellspacing="0" cellpadding="0" border="0" height="100%">
- <tr>
- <td id="lefttext" valign="top">
-<h1>Fresh Install</h1>
-It's extremely easy to set up eAthena, just follow these simple steps.
-<ol>
- <li>Edit motd.txt, grf-files.txt and the .conf files in your /conf/ folder as you see fit</li>
- <li>If you want to add a user, edit save/account.txt in the main eAthena directory before starting the server.</li>
- <li>Run runserver.bat or runserver-sql.bat (depending on which storage system you're using, or you could run login-server.exe, char-server.exe, and map-server.exe manually)</li>
- <li>Give people your IP address (can be found at <a href="http://www.whatismyip.com">http://www.whatismyip.com</a>) to people to add in their sclientinfo.xml</li>
- <li>You're done!</li>
- </td>
- <td id="midtext">
- </td>
- <td id="righttext" valign="top">
-<h1>Upgrading</h1>
-When you're changing versions of eAthena, it is important to keep your saved files in tact. Locate the files (/save/ in TXT, your SQL databse in SQL) and make a back up.
-You also might want to back up any changes you did to eAthena, such as custom sprites/items, open-source changes.
-After backing it up, change motd.txt, grf-files.txt, and the .conf files in the /conf/ folder to your old settings. It is
-important that you use a fresh eAthena, as it changes in structure and many files will have different formats over time.
-Put your backed up files back in, and run eAthena like you normally would.
-
- </td>
- </tr>
- <tr>
- <td colspan="3">
- &copy; Content Copyright 2005 eAthena Development Team/Evera<br>
- &copy; Design Copyright 2005 Evera
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
- </td>
- <td id="rightborder" valign="top">
- <table cellspacing="0" cellpadding="0" border="0">
- <tr>
- <td id="rightborderspacer">
- </td>
- </tr>
- <tr>
- <td valign="top">
- <img src="./images/rightborder.gif">
- </td>
- </tr>
- </table>
- </td>
-
- </tr>
-
-</table>
-</div>
-
+<html>
+ <head>
+ <title>eAthena | Setup</title>
+ <link rel="stylesheet" type="text/css" href="style.css">
+ </head>
+ <body>
+ <div id="template">
+ <div id="header">
+ <div class="logo">eAthena<br /><span class="subtitle">- RAGNAROK Online Server Emulator</span></div>
+ <div class="title">Setup</div>
+ </div>
+ <div id="navcontainer">
+ <ul id="navlist">
+ <li><a href="../readme.html">Intro</a></li>
+ <li><a href="setup.html">Setup</a></li>
+ <li><a href="faq.html">FAQ</a></li>
+ <li><a href="scripting.html">Scripting</a></li>
+ <li><a href="commands.html">GM Commands</a></li>
+ <li><a href="resources.html">Resources</a></li>
+ </ul>
+ </div>
+
+ <div class="body-container">
+ <strong>Character Server:<br></strong>
+ <ol>
+ <li>Open /conf/char_athena.conf</li>
+ <li>Change userid and passwd (s1/p1) to what you want your server's communication details to be.</li>
+ <li>Change Server_Name to what you want to call your server.</li>
+ <li>Remove the <strong>//</strong> before login_ip.
+ <li>Remove the <strong>//</strong> before char_ip and change 127.0.0.1 to your <a href="http://www.whatismyip.com" target="_new">WAN IP</a>.
+ </ol>
+
+ <strong>Map Server:<br></strong>
+ <ol>
+ <li>Open /conf/map_athena.conf</li>
+ <li>Change userid and passwd to the same thing you set in char_athena.</li>
+ <li>Remove the <strong>//</strong> before char_ip.</li>
+ <li>Remove the <strong>//</strong> before map_ip and change 127.0.0.1 to your <a href="http://www.whatismyip.com" target="_new">WAN IP</a>.
+ </ol>
+
+ <strong>Subnet:<br></strong>
+ <ol>
+ <li>Open /conf/subnet_athena.conf</li>
+ <li>Change 255.0.0.0 to your <strong>"Subnet Mask"</strong>, change the two 127.0.0.1 to your <strong>LAN IP</strong>.
+ </ol>
+
+ <strong>MySQL Settings:<br></strong>
+ <ol>
+ <li>Open /conf/inter_athena.conf</li>
+ <li>Find the "Global SQL Settings" and change them to your SQL server's settings.</li>
+ </ol>
+
+ <strong>Message of the Day:<br></strong>
+ <ol>
+ <li>Open /conf/motd.txt and edit it to change the in-game MOTD.</li>
+ </ol>
+ </div>
+
+ <div id="footer">"Read Me" Created & Designed by <a href="http://www.kisuka.com" target="_new">Kisuka</a></div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/readme/style.css b/readme/style.css
new file mode 100644
index 000000000..7a7a3732a
--- /dev/null
+++ b/readme/style.css
@@ -0,0 +1,80 @@
+/* Created by Kisuka */
+/* www.kisuka.com */
+html, body {
+ height: 100%;
+ margin: 0;
+ background-image:url(images/bg.gif);
+}
+body {
+ width: 900px;
+ height: 100%;
+ border-left:thin solid #000;
+ border-right:thin solid #000;
+ margin-left:auto;
+ margin-right:auto;
+ background:#FFF url(images/clown.png) no-repeat fixed right bottom;
+}
+#template { position:relative; min-height:100%; }
+* html #template { height: 100%; }
+#header {
+ height: 60px;
+ border-bottom:thin solid #000;
+}
+.logo {
+ float:left;
+ padding-left:25px;
+ font-size:x-large;
+}
+.title {
+ float:right;
+ padding-right:25px;
+ font-size:xx-large;
+ padding-top:10px;
+}
+.body-title {
+ font-size:x-large;
+}
+.subtitle {
+ font-size:14px;
+ padding-left:10px;
+ font-style:italic;
+}
+.body-container {
+ padding-left:30px;
+ padding-right:30px;
+}
+#navcontainer ul {
+padding-left: 0;
+margin-left: 0;
+margin-top:0;
+background-color: #000;
+color: White;
+float: left;
+width: 100%;
+font-family: arial, helvetica, sans-serif;
+}
+#navcontainer ul li { display: inline; }
+#navcontainer ul li a {
+ padding: 0.2em 1em;
+ background-color: #000;
+ color: White;
+ text-decoration: none;
+ float: left;
+ border-right: 1px solid #fff;
+}
+#navcontainer ul li a:hover {
+ background-color: #666;
+ color: #fff;
+}
+#footer {
+ background-color: #000;
+ width: 100%;
+ color: White;
+ position:absolute;
+ bottom:0;
+ text-align:center;
+ border-top: 1px solid #fff;
+}
+#footer a {
+ color: White;
+} \ No newline at end of file
diff --git a/sql-files/logs.sql b/sql-files/logs.sql
index 177dee870..6a69e3e1f 100644
--- a/sql-files/logs.sql
+++ b/sql-files/logs.sql
@@ -1,7 +1,7 @@
#PickLog types (M)onsters Drop, (P)layers Drop/Take, Mobs Drop (L)oot Drop/Take,
# Players (T)rade Give/Take, Players (V)ending Sell/Take, (S)hop Sell/Take, (N)PC Give/Take,
# (C)onsumable Items, (A)dministrators Create/Delete, Sto(R)age, (G)uild Storage,
-# (E)mail attachment
+# (E)mail attachment,(B)uying Store
#Database: log
#Table: picklog
@@ -9,7 +9,7 @@ CREATE TABLE `picklog` (
`id` int(11) NOT NULL auto_increment,
`time` datetime NOT NULL default '0000-00-00 00:00:00',
`char_id` int(11) NOT NULL default '0',
- `type` enum('M','P','L','T','V','S','N','C','A','R','G','E') NOT NULL default 'P',
+ `type` enum('M','P','L','T','V','S','N','C','A','R','G','E','B') NOT NULL default 'P',
`nameid` int(11) NOT NULL default '0',
`amount` int(11) NOT NULL default '1',
`refine` tinyint(3) unsigned NOT NULL default '0',
@@ -22,7 +22,7 @@ CREATE TABLE `picklog` (
INDEX (`type`)
) ENGINE=MyISAM AUTO_INCREMENT=1 ;
-#ZenyLog types (M)onsters,(T)rade,(V)ending Sell/Buy,(S)hop Sell/Buy,(N)PC Change amount,(A)dministrators,(E)Mail
+#ZenyLog types (M)onsters,(T)rade,(V)ending Sell/Buy,(S)hop Sell/Buy,(N)PC Change amount,(A)dministrators,(E)Mail,(B)uying Store
#Database: log
#Table: zenylog
CREATE TABLE `zenylog` (
@@ -30,7 +30,7 @@ CREATE TABLE `zenylog` (
`time` datetime NOT NULL default '0000-00-00 00:00:00',
`char_id` int(11) NOT NULL default '0',
`src_id` int(11) NOT NULL default '0',
- `type` enum('M','T','V','S','N','A','E') NOT NULL default 'S',
+ `type` enum('M','T','V','S','N','A','E','B') NOT NULL default 'S',
`amount` int(11) NOT NULL default '0',
`map` varchar(11) NOT NULL default '',
PRIMARY KEY (`id`),
diff --git a/sql-files/main.sql b/sql-files/main.sql
index 55cc8b4bc..dae3300e4 100644
--- a/sql-files/main.sql
+++ b/sql-files/main.sql
@@ -101,6 +101,7 @@ CREATE TABLE IF NOT EXISTS `char` (
`child` int(11) unsigned NOT NULL default '0',
`fame` int(11) unsigned NOT NULL default '0',
`rename` SMALLINT(3) unsigned NOT NULL default '0',
+ `delete_date` INT(11) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`char_id`),
KEY `account_id` (`account_id`),
KEY `party_id` (`party_id`),
diff --git a/sql-files/upgrade_svn14700.sql b/sql-files/upgrade_svn14700.sql
new file mode 100644
index 000000000..a1e3d8ddb
--- /dev/null
+++ b/sql-files/upgrade_svn14700.sql
@@ -0,0 +1 @@
+ALTER TABLE `char` ADD `delete_date` INT(11) UNSIGNED NOT NULL DEFAULT '0';
diff --git a/sql-files/upgrade_svn14713_log.sql b/sql-files/upgrade_svn14713_log.sql
new file mode 100644
index 000000000..be4059ebe
--- /dev/null
+++ b/sql-files/upgrade_svn14713_log.sql
@@ -0,0 +1,4 @@
+-- Adds 'B' to `type` in `picklog` and `zenylog`
+
+ALTER TABLE `picklog` MODIFY `type` ENUM('M','P','L','T','V','S','N','C','A','R','G','E','B') NOT NULL DEFAULT 'P';
+ALTER TABLE `zenylog` MODIFY `type` ENUM('M','T','V','S','N','A','E','B') NOT NULL DEFAULT 'S';
diff --git a/src/char/char.c b/src/char/char.c
index 6523decf7..b499faf96 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -85,6 +85,7 @@ char char_name_letters[1024] = ""; // list of letters/symbols allowed (or not) i
int char_per_account = 0; //Maximum charas per account (default unlimited) [Sirius]
int char_del_level = 0; //From which level u can delete character [Lupus]
+int char_del_delay = 86400;
int log_char = 1; // loggin char or not [devil]
int log_inter = 1; // loggin inter or not [devil]
@@ -106,6 +107,7 @@ struct char_session_data {
int gmlevel;
uint32 version;
uint8 clienttype;
+ char birthdate[10+1]; // YYYY-MM-DD
};
int char_id_count = START_CHAR_NUM;
@@ -368,6 +370,48 @@ int char_log(char *fmt, ...)
return 0;
}
+
+/// Find all characters for given session and update the session character cache.
+int char_find_characters(struct char_session_data* sd)
+{
+ int i, found_num = 0;
+
+ for( i = 0; i < char_num; i++ )
+ {// find character entries and save them
+ if( char_dat[i].status.account_id == sd->account_id )
+ {
+ sd->found_char[found_num++] = i;
+
+ if( found_num >= MAX_CHARS )
+ {
+ break;
+ }
+ }
+ }
+
+ for( i = found_num; i < MAX_CHARS; i++ )
+ {// fill remaining blanks
+ sd->found_char[i] = -1;
+ }
+
+ return found_num;
+}
+
+
+/// Search character data from given session.
+struct mmo_charstatus* search_session_character(struct char_session_data* sd, int char_id)
+{
+ int i;
+
+ ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] != -1 && char_dat[sd->found_char[i]].status.char_id == char_id );
+ if( i == MAX_CHARS )
+ {
+ return NULL;
+ }
+ return &char_dat[sd->found_char[i]].status;
+}
+
+
//Search character data from the aid/cid givem
struct mmo_charstatus* search_character(int aid, int cid)
{
@@ -483,7 +527,7 @@ int mmo_char_tostr(char *str, struct mmo_charstatus *p, struct global_reg *reg,
"\t%d,%d,%d\t%d,%d,%d,%d" //Up to hom id
"\t%d,%d,%d\t%d,%d,%d,%d,%d" //Up to head bottom
"\t%d,%d,%d\t%d,%d,%d" //last point + save point
- ",%d,%d,%d,%d,%d\t", //Family info
+ ",%d,%d,%d,%d,%d,%lu\t", //Family info + delete date
p->char_id, p->account_id, p->slot, p->name, //
p->class_, p->base_level, p->job_level,
p->base_exp, p->job_exp, p->zeny,
@@ -496,7 +540,8 @@ int mmo_char_tostr(char *str, struct mmo_charstatus *p, struct global_reg *reg,
p->weapon, p->shield, p->head_top, p->head_mid, p->head_bottom,
p->last_point.map, p->last_point.x, p->last_point.y, //
p->save_point.map, p->save_point.x, p->save_point.y,
- p->partner_id,p->father,p->mother,p->child,p->fame);
+ p->partner_id,p->father,p->mother,p->child,p->fame, //
+ (unsigned long)p->delete_date); // FIXME: platform-dependent size
for(i = 0; i < MAX_MEMOPOINTS; i++)
if (p->memo_point[i].map) {
str_p += sprintf(str_p, "%d,%d,%d ", p->memo_point[i].map, p->memo_point[i].x, p->memo_point[i].y);
@@ -549,10 +594,30 @@ int mmo_char_fromstr(char *str, struct mmo_charstatus *p, struct global_reg *reg
int tmp_int[256];
unsigned int tmp_uint[2]; //To read exp....
int next, len, i, j;
+ unsigned long tmp_ulong[1];
// initilialise character
memset(p, '\0', sizeof(struct mmo_charstatus));
+// Char structure of version 146xx (delete date)
+ if (sscanf(str, "%d\t%d,%d\t%127[^\t]\t%d,%d,%d\t%u,%u,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d"
+ "\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d"
+ "\t%d,%d,%d\t%d,%d,%d,%d,%d,%d,%d,%d,%lu%n",
+ &tmp_int[0], &tmp_int[1], &tmp_int[2], tmp_str[0],
+ &tmp_int[3], &tmp_int[4], &tmp_int[5],
+ &tmp_uint[0], &tmp_uint[1], &tmp_int[8],
+ &tmp_int[9], &tmp_int[10], &tmp_int[11], &tmp_int[12],
+ &tmp_int[13], &tmp_int[14], &tmp_int[15], &tmp_int[16], &tmp_int[17], &tmp_int[18],
+ &tmp_int[19], &tmp_int[20],
+ &tmp_int[21], &tmp_int[22], &tmp_int[23], //
+ &tmp_int[24], &tmp_int[25], &tmp_int[26], &tmp_int[44],
+ &tmp_int[27], &tmp_int[28], &tmp_int[29],
+ &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], &tmp_int[34],
+ &tmp_int[45], &tmp_int[35], &tmp_int[36],
+ &tmp_int[46], &tmp_int[37], &tmp_int[38], &tmp_int[39],
+ &tmp_int[40], &tmp_int[41], &tmp_int[42], &tmp_int[43], &tmp_ulong[0], &next) != 49)
+ {
+ tmp_ulong[0] = 0; // delete date
// Char structure of version 1500 (homun + mapindex maps)
if (sscanf(str, "%d\t%d,%d\t%127[^\t]\t%d,%d,%d\t%u,%u,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d"
"\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d"
@@ -677,6 +742,7 @@ int mmo_char_fromstr(char *str, struct mmo_charstatus *p, struct global_reg *reg
tmp_int[45] = mapindex_name2id(tmp_str[1]);
tmp_int[46] = mapindex_name2id(tmp_str[2]);
} // Char structure of version 1500 (homun + mapindex maps)
+ } // Char structure of version 146xx (delete date)
safestrncpy(p->name, tmp_str[0], NAME_LENGTH); //Overflow protection [Skotlex]
p->char_id = tmp_int[0];
@@ -726,6 +792,7 @@ int mmo_char_fromstr(char *str, struct mmo_charstatus *p, struct global_reg *reg
p->hom_id = tmp_int[44];
p->last_point.map = tmp_int[45];
p->save_point.map = tmp_int[46];
+ p->delete_date = tmp_ulong[0];
#ifndef TXT_SQL_CONVERT
// Some checks
@@ -1705,7 +1772,7 @@ int count_users(void)
// Writes char data to the buffer in the format used by the client.
// Used in packets 0x6b (chars info) and 0x6d (new char info)
// Returns the size
-#define MAX_CHAR_BUF 110 //Max size (for WFIFOHEAD calls)
+#define MAX_CHAR_BUF 132 //Max size (for WFIFOHEAD calls)
int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
{
unsigned short offset = 0;
@@ -1765,6 +1832,10 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
mapindex_getmapname_ext(mapindex_id2name(p->last_point.map), (char*)WBUFP(buf,108));
offset += MAP_NAME_LENGTH_EXT;
#endif
+#if PACKETVER >= 20100803
+ WBUFL(buf,124) = TOL(p->delete_date);
+ offset += 4;
+#endif
return 106+offset;
}
@@ -1778,16 +1849,7 @@ int mmo_char_send006b(int fd, struct char_session_data* sd)
offset += 3;
#endif
- found_num = 0;
- for(i = 0; i < char_num; i++) {
- if (char_dat[i].status.account_id == sd->account_id) {
- sd->found_char[found_num] = i;
- if( ++found_num == MAX_CHARS )
- break;
- }
- }
- for(i = found_num; i < MAX_CHARS; i++)
- sd->found_char[i] = -1;
+ found_num = char_find_characters(sd);
j = 24 + offset; // offset
WFIFOHEAD(fd,j + found_num*MAX_CHAR_BUF);
@@ -2064,7 +2126,7 @@ int parse_fromlogin(int fd)
break;
case 0x2717: // account data
- if (RFIFOREST(fd) < 51)
+ if (RFIFOREST(fd) < 62)
return 0;
// find the authenticated session with this account id
@@ -2074,6 +2136,7 @@ int parse_fromlogin(int fd)
memcpy(sd->email, RFIFOP(fd,6), 40);
sd->expiration_time = (time_t)RFIFOL(fd,46);
sd->gmlevel = RFIFOB(fd,50);
+ safestrncpy(sd->birthdate, RFIFOP(fd,51), sizeof(sd->birthdate));
// continued from char_auth_ok...
if( max_connect_user && count_users() >= max_connect_user && sd->gmlevel < gm_allow_level )
@@ -2089,7 +2152,7 @@ int parse_fromlogin(int fd)
mmo_char_send006b(i, sd);
}
}
- RFIFOSKIP(fd,51);
+ RFIFOSKIP(fd,62);
break;
// login-server alive packet
@@ -3155,6 +3218,211 @@ int lan_subnetcheck(uint32 ip)
}
}
+
+/// @param result
+/// 0 (0x718): An unknown error has occurred.
+/// 1: none/success
+/// 3 (0x719): A database error occurred.
+/// 4 (0x71a): To delete a character you must withdraw from the guild.
+/// 5 (0x71b): To delete a character you must withdraw from the party.
+/// Any (0x718): An unknown error has occurred.
+void char_delete2_ack(int fd, int char_id, uint32 result, time_t delete_date)
+{// HC: <0828>.W <char id>.L <Msg:0-5>.L <deleteDate>.L
+ WFIFOHEAD(fd,14);
+ WFIFOW(fd,0) = 0x828;
+ WFIFOL(fd,2) = char_id;
+ WFIFOL(fd,6) = result;
+ WFIFOL(fd,10) = TOL(delete_date);
+ WFIFOSET(fd,14);
+}
+
+
+/// @param result
+/// 0 (0x718): An unknown error has occurred.
+/// 1: none/success
+/// 2 (0x71c): Due to system settings can not be deleted.
+/// 3 (0x719): A database error occurred.
+/// 4 (0x71d): Deleting not yet possible time.
+/// 5 (0x71e): Date of birth do not match.
+/// Any (0x718): An unknown error has occurred.
+void char_delete2_accept_ack(int fd, int char_id, uint32 result)
+{// HC: <082a>.W <char id>.L <Msg:0-5>.L
+ WFIFOHEAD(fd,10);
+ WFIFOW(fd,0) = 0x82a;
+ WFIFOL(fd,2) = char_id;
+ WFIFOL(fd,6) = result;
+ WFIFOSET(fd,10);
+}
+
+
+/// @param result
+/// 1 (0x718): none/success, (if char id not in deletion process): An unknown error has occurred.
+/// 2 (0x719): A database error occurred.
+/// Any (0x718): An unknown error has occurred.
+void char_delete2_cancel_ack(int fd, int char_id, uint32 result)
+{// HC: <082c>.W <char id>.L <Msg:1-2>.L
+ WFIFOHEAD(fd,10);
+ WFIFOW(fd,0) = 0x82c;
+ WFIFOL(fd,2) = char_id;
+ WFIFOL(fd,6) = result;
+ WFIFOSET(fd,10);
+}
+
+
+static void char_delete2_req(int fd, struct char_session_data* sd)
+{// CH: <0827>.W <char id>.L
+ int char_id;
+ struct mmo_charstatus* cs;
+
+ char_id = RFIFOL(fd,2);
+
+ if( ( cs = search_session_character(sd, char_id) ) == NULL )
+ {// character not found
+ char_delete2_ack(fd, char_id, 3, 0);
+ return;
+ }
+
+ if( cs->delete_date )
+ {// character already queued for deletion
+ char_delete2_ack(fd, char_id, 0, 0);
+ return;
+ }
+
+/*
+ // Aegis imposes these checks probably to avoid dead member
+ // entries in guilds/parties, otherwise they are not required.
+ // TODO: Figure out how these are enforced during waiting.
+ if( cs->guild_id )
+ {// character in guild
+ char_delete2_ack(fd, char_id, 4, 0);
+ return;
+ }
+
+ if( cs->party_id )
+ {// character in party
+ char_delete2_ack(fd, char_id, 5, 0);
+ return;
+ }
+*/
+
+ // success
+ cs->delete_date = time(NULL)+char_del_delay;
+
+ char_delete2_ack(fd, char_id, 1, cs->delete_date);
+}
+
+
+static void char_delete2_accept(int fd, struct char_session_data* sd)
+{// CH: <0829>.W <char id>.L <birth date:YYMMDD>.6B
+ char birthdate[8+1];
+ int char_id, i;
+ struct mmo_charstatus* cs;
+
+ char_id = RFIFOL(fd,2);
+
+ ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, char_id);
+
+ // construct "YY-MM-DD"
+ birthdate[0] = RFIFOB(fd,6);
+ birthdate[1] = RFIFOB(fd,7);
+ birthdate[2] = '-';
+ birthdate[3] = RFIFOB(fd,8);
+ birthdate[4] = RFIFOB(fd,9);
+ birthdate[5] = '-';
+ birthdate[6] = RFIFOB(fd,10);
+ birthdate[7] = RFIFOB(fd,11);
+ birthdate[8] = 0;
+
+ ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] != -1 && char_dat[sd->found_char[i]].status.char_id == char_id );
+ if( i == MAX_CHARS )
+ {// character not found
+ char_delete2_accept_ack(fd, char_id, 3);
+ return;
+ }
+ cs = &char_dat[sd->found_char[i]].status;
+
+ if( !cs->delete_date || cs->delete_date>time(NULL) )
+ {// not queued or delay not yet passed
+ char_delete2_accept_ack(fd, char_id, 4);
+ return;
+ }
+
+ if( strcmp(sd->birthdate+2, birthdate) ) // +2 to cut off the century
+ {// birth date is wrong
+ char_delete2_accept_ack(fd, char_id, 5);
+ return;
+ }
+
+ if( ( char_del_level > 0 && cs->base_level >= (unsigned int)char_del_level ) || ( char_del_level < 0 && cs->base_level <= (unsigned int)(-char_del_level) ) )
+ {// character level config restriction
+ char_delete2_accept_ack(fd, char_id, 2);
+ return;
+ }
+
+ // success
+ char_delete(cs);
+
+ // drop character entry
+ if( --char_num > 0 && sd->found_char[i] != char_num )
+ {
+ int s, c;
+
+ // move the last entry to the place of the deleted character
+ memcpy(&char_dat[sd->found_char[i]], &char_dat[char_num], sizeof(struct mmo_charstatus));
+
+ // scan currently online accounts, if the moved character
+ // entry requires an update of the cached character list
+ for( s = 0; s < fd_max; s++ )
+ {
+ struct char_session_data* osd;
+
+ if( session[s] && ( osd = (struct char_session_data*)session[s]->session_data ) != NULL && osd->account_id == char_dat[char_num].status.account_id )
+ {
+ for( c = 0; c < MAX_CHARS; c++ )
+ {
+ if( osd->found_char[c] == char_num )
+ {
+ osd->found_char[c] = sd->found_char[i];
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ // wipe the last entry
+ memset(&char_dat[char_num], 0, sizeof(struct mmo_charstatus));
+ }
+
+ // refresh character list cache
+ char_find_characters(sd);
+
+ char_delete2_accept_ack(fd, char_id, 1);
+}
+
+
+static void char_delete2_cancel(int fd, struct char_session_data* sd)
+{// CH: <082b>.W <char id>.L
+ int char_id;
+ struct mmo_charstatus* cs;
+
+ char_id = RFIFOL(fd,2);
+
+ if( ( cs = search_session_character(sd, char_id) ) == NULL )
+ {// character not found
+ char_delete2_cancel_ack(fd, char_id, 2);
+ return;
+ }
+
+ // there is no need to check, whether or not the character was
+ // queued for deletion, as the client prints an error message by
+ // itself, if it was not the case (@see char_delete2_cancel_ack)
+ cs->delete_date = 0;
+
+ char_delete2_cancel_ack(fd, char_id, 1);
+}
+
+
int parse_char(int fd)
{
int i, ch;
@@ -3600,6 +3868,27 @@ int parse_char(int fd)
RFIFOSKIP(fd,32);
break;
+ // deletion timer request
+ case 0x827:
+ FIFOSD_CHECK(6);
+ char_delete2_req(fd, sd);
+ RFIFOSKIP(fd,6);
+ break;
+
+ // deletion accept request
+ case 0x829:
+ FIFOSD_CHECK(12);
+ char_delete2_accept(fd, sd);
+ RFIFOSKIP(fd,12);
+ break;
+
+ // deletion cancel request
+ case 0x82b:
+ FIFOSD_CHECK(6);
+ char_delete2_cancel(fd, sd);
+ RFIFOSKIP(fd,6);
+ break;
+
// login as map-server
case 0x2af8:
if (RFIFOREST(fd) < 60)
@@ -4056,6 +4345,8 @@ int char_config_read(const char *cfgName)
char_per_account = atoi(w2);
} else if (strcmpi(w1, "char_del_level") == 0) { //disable/enable char deletion by its level condition [Lupus]
char_del_level = atoi(w2);
+ } else if (strcmpi(w1, "char_del_delay") == 0) {
+ char_del_delay = atoi(w2);
// online files options
} else if (strcmpi(w1, "online_txt_filename") == 0) {
safestrncpy(online_txt_filename, w2, sizeof(online_txt_filename));
diff --git a/src/char_sql/char.c b/src/char_sql/char.c
index 262f585d2..e135fee78 100644
--- a/src/char_sql/char.c
+++ b/src/char_sql/char.c
@@ -109,6 +109,7 @@ char char_name_letters[1024] = ""; // list of letters/symbols allowed (or not) i
int char_per_account = 0; //Maximum charas per account (default unlimited) [Sirius]
int char_del_level = 0; //From which level u can delete character [Lupus]
+int char_del_delay = 86400;
int log_char = 1; // loggin char or not [devil]
int log_inter = 1; // loggin inter or not [devil]
@@ -131,6 +132,7 @@ struct char_session_data {
uint32 version;
uint8 clienttype;
char new_name[NAME_LENGTH];
+ char birthdate[10+1]; // YYYY-MM-DD
};
int max_connect_user = 0;
@@ -471,7 +473,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
(p->party_id != cp->party_id) || (p->guild_id != cp->guild_id) ||
(p->pet_id != cp->pet_id) || (p->weapon != cp->weapon) || (p->hom_id != cp->hom_id) ||
(p->shield != cp->shield) || (p->head_top != cp->head_top) ||
- (p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom)
+ (p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date)
)
{ //Save status
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d',"
@@ -480,7 +482,8 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
"`str`='%d',`agi`='%d',`vit`='%d',`int`='%d',`dex`='%d',`luk`='%d',"
"`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d',"
"`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'"
+ "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d',"
+ "`delete_date`='%lu'"
" WHERE `account_id`='%d' AND `char_id` = '%d'",
char_db, p->base_level, p->job_level,
p->base_exp, p->job_exp, p->zeny,
@@ -490,6 +493,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
p->weapon, p->shield, p->head_top, p->head_mid, p->head_bottom,
mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y,
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->account_id, p->char_id) )
{
Sql_ShowDebug(sql_handle);
@@ -839,7 +843,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
"`char_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`,"
"`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`,"
"`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`,"
- "`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`"
+ "`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`"
" FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", 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)
@@ -876,6 +880,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT, &p.head_bottom, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_SHORT, &p.rename, 0, NULL, NULL)
+ || SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL)
)
{
SqlStmt_ShowDebug(stmt);
@@ -934,7 +939,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
"`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`,"
"`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`hair`,"
"`hair_color`,`clothes_color`,`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`"
+ "`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`"
" FROM `%s` WHERE `char_id`=? LIMIT 1", char_db)
|| SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SqlStmt_Execute(stmt)
@@ -987,6 +992,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 46, SQLDT_INT, &p->child, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 47, SQLDT_INT, &p->fame, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 48, SQLDT_SHORT, &p->rename, 0, NULL, NULL)
+ || SQL_ERROR == SqlStmt_BindColumn(stmt, 49, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL)
)
{
SqlStmt_ShowDebug(stmt);
@@ -1407,6 +1413,7 @@ int delete_char_sql(int char_id)
Sql_FreeResult(sql_handle);
//check for config char del condition [Lupus]
+ // TODO: Move this out to packet processing (0x68/0x1fb).
if( ( char_del_level > 0 && base_level >= char_del_level )
|| ( char_del_level < 0 && base_level <= -char_del_level )
) {
@@ -1542,7 +1549,7 @@ int count_users(void)
// Writes char data to the buffer in the format used by the client.
// Used in packets 0x6b (chars info) and 0x6d (new char info)
// Returns the size
-#define MAX_CHAR_BUF 110 //Max size (for WFIFOHEAD calls)
+#define MAX_CHAR_BUF 132 //Max size (for WFIFOHEAD calls)
int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
{
unsigned short offset = 0;
@@ -1602,6 +1609,10 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
mapindex_getmapname_ext(mapindex_id2name(p->last_point.map), (char*)WBUFP(buf,108));
offset += MAP_NAME_LENGTH_EXT;
#endif
+#if PACKETVER >= 20100803
+ WBUFL(buf,124) = TOL(p->delete_date);
+ offset += 4;
+#endif
return 106+offset;
}
@@ -1849,7 +1860,7 @@ int parse_fromlogin(int fd)
break;
case 0x2717: // account data
- if (RFIFOREST(fd) < 51)
+ if (RFIFOREST(fd) < 62)
return 0;
// find the authenticated session with this account id
@@ -1859,6 +1870,7 @@ int parse_fromlogin(int fd)
memcpy(sd->email, RFIFOP(fd,6), 40);
sd->expiration_time = (time_t)RFIFOL(fd,46);
sd->gmlevel = RFIFOB(fd,50);
+ safestrncpy(sd->birthdate, RFIFOP(fd,51), sizeof(sd->birthdate));
// continued from char_auth_ok...
if( max_connect_user && count_users() >= max_connect_user && sd->gmlevel < gm_allow_level )
@@ -1874,7 +1886,7 @@ int parse_fromlogin(int fd)
mmo_char_send006b(i, sd);
}
}
- RFIFOSKIP(fd,51);
+ RFIFOSKIP(fd,62);
break;
// login-server alive packet
@@ -2961,6 +2973,223 @@ int lan_subnetcheck(uint32 ip)
}
}
+
+/// @param result
+/// 0 (0x718): An unknown error has occurred.
+/// 1: none/success
+/// 3 (0x719): A database error occurred.
+/// 4 (0x71a): To delete a character you must withdraw from the guild.
+/// 5 (0x71b): To delete a character you must withdraw from the party.
+/// Any (0x718): An unknown error has occurred.
+void char_delete2_ack(int fd, int char_id, uint32 result, time_t delete_date)
+{// HC: <0828>.W <char id>.L <Msg:0-5>.L <deleteDate>.L
+ WFIFOHEAD(fd,14);
+ WFIFOW(fd,0) = 0x828;
+ WFIFOL(fd,2) = char_id;
+ WFIFOL(fd,6) = result;
+ WFIFOL(fd,10) = TOL(delete_date);
+ WFIFOSET(fd,14);
+}
+
+
+/// @param result
+/// 0 (0x718): An unknown error has occurred.
+/// 1: none/success
+/// 2 (0x71c): Due to system settings can not be deleted.
+/// 3 (0x719): A database error occurred.
+/// 4 (0x71d): Deleting not yet possible time.
+/// 5 (0x71e): Date of birth do not match.
+/// Any (0x718): An unknown error has occurred.
+void char_delete2_accept_ack(int fd, int char_id, uint32 result)
+{// HC: <082a>.W <char id>.L <Msg:0-5>.L
+ WFIFOHEAD(fd,10);
+ WFIFOW(fd,0) = 0x82a;
+ WFIFOL(fd,2) = char_id;
+ WFIFOL(fd,6) = result;
+ WFIFOSET(fd,10);
+}
+
+
+/// @param result
+/// 1 (0x718): none/success, (if char id not in deletion process): An unknown error has occurred.
+/// 2 (0x719): A database error occurred.
+/// Any (0x718): An unknown error has occurred.
+void char_delete2_cancel_ack(int fd, int char_id, uint32 result)
+{// HC: <082c>.W <char id>.L <Msg:1-2>.L
+ WFIFOHEAD(fd,10);
+ WFIFOW(fd,0) = 0x82c;
+ WFIFOL(fd,2) = char_id;
+ WFIFOL(fd,6) = result;
+ WFIFOSET(fd,10);
+}
+
+
+static void char_delete2_req(int fd, struct char_session_data* sd)
+{// CH: <0827>.W <char id>.L
+ int char_id, i, guild_id, party_id;
+ char* data;
+ time_t delete_date;
+
+ char_id = RFIFOL(fd,2);
+
+ ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
+ if( i == MAX_CHARS )
+ {// character not found
+ char_delete2_ack(fd, char_id, 3, 0);
+ return;
+ }
+
+ if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `guild_id`,`party_id`,`delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) )
+ {
+ Sql_ShowDebug(sql_handle);
+ char_delete2_ack(fd, char_id, 3, 0);
+ return;
+ }
+
+ Sql_GetData(sql_handle, 0, &data, NULL); guild_id = atoi(data);
+ Sql_GetData(sql_handle, 1, &data, NULL); party_id = atoi(data);
+ Sql_GetData(sql_handle, 2, &data, NULL); delete_date = strtoul(data, NULL, 10);
+
+ if( delete_date )
+ {// character already queued for deletion
+ char_delete2_ack(fd, char_id, 0, 0);
+ return;
+ }
+
+/*
+ // Aegis imposes these checks probably to avoid dead member
+ // entries in guilds/parties, otherwise they are not required.
+ // TODO: Figure out how these are enforced during waiting.
+ if( guild_id )
+ {// character in guild
+ char_delete2_ack(fd, char_id, 4, 0);
+ return;
+ }
+
+ if( party_id )
+ {// character in party
+ char_delete2_ack(fd, char_id, 5, 0);
+ return;
+ }
+*/
+
+ // success
+ delete_date = time(NULL)+char_del_delay;
+
+ if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='%lu' WHERE `char_id`='%d'", char_db, (unsigned long)delete_date, char_id) )
+ {
+ Sql_ShowDebug(sql_handle);
+ char_delete2_ack(fd, char_id, 3, 0);
+ return;
+ }
+
+ char_delete2_ack(fd, char_id, 1, delete_date);
+}
+
+
+static void char_delete2_accept(int fd, struct char_session_data* sd)
+{// CH: <0829>.W <char id>.L <birth date:YYMMDD>.6B
+ char birthdate[8+1];
+ int char_id, i, k;
+ unsigned int base_level;
+ char* data;
+ time_t delete_date;
+
+ char_id = RFIFOL(fd,2);
+
+ ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, char_id);
+
+ // construct "YY-MM-DD"
+ birthdate[0] = RFIFOB(fd,6);
+ birthdate[1] = RFIFOB(fd,7);
+ birthdate[2] = '-';
+ birthdate[3] = RFIFOB(fd,8);
+ birthdate[4] = RFIFOB(fd,9);
+ birthdate[5] = '-';
+ birthdate[6] = RFIFOB(fd,10);
+ birthdate[7] = RFIFOB(fd,11);
+ birthdate[8] = 0;
+
+ ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
+ if( i == MAX_CHARS )
+ {// character not found
+ char_delete2_accept_ack(fd, char_id, 3);
+ return;
+ }
+
+ if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `base_level`,`delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) )
+ {// data error
+ Sql_ShowDebug(sql_handle);
+ char_delete2_accept_ack(fd, char_id, 3);
+ return;
+ }
+
+ Sql_GetData(sql_handle, 0, &data, NULL); base_level = (unsigned int)strtoul(data, NULL, 10);
+ Sql_GetData(sql_handle, 1, &data, NULL); delete_date = strtoul(data, NULL, 10);
+
+ if( !delete_date || delete_date>time(NULL) )
+ {// not queued or delay not yet passed
+ char_delete2_accept_ack(fd, char_id, 4);
+ return;
+ }
+
+ if( strcmp(sd->birthdate+2, birthdate) ) // +2 to cut off the century
+ {// birth date is wrong
+ char_delete2_accept_ack(fd, char_id, 5);
+ return;
+ }
+
+ if( ( char_del_level > 0 && base_level >= (unsigned int)char_del_level ) || ( char_del_level < 0 && base_level <= (unsigned int)(-char_del_level) ) )
+ {// character level config restriction
+ char_delete2_accept_ack(fd, char_id, 2);
+ return;
+ }
+
+ // success
+ if( delete_char_sql(char_id) < 0 )
+ {
+ char_delete2_accept_ack(fd, char_id, 3);
+ return;
+ }
+
+ // refresh character list cache
+ for(k = i; k < MAX_CHARS-1; k++)
+ {
+ sd->found_char[k] = sd->found_char[k+1];
+ }
+ sd->found_char[MAX_CHARS-1] = -1;
+
+ char_delete2_accept_ack(fd, char_id, 1);
+}
+
+
+static void char_delete2_cancel(int fd, struct char_session_data* sd)
+{// CH: <082b>.W <char id>.L
+ int char_id, i;
+
+ char_id = RFIFOL(fd,2);
+
+ ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
+ if( i == MAX_CHARS )
+ {// character not found
+ char_delete2_cancel_ack(fd, char_id, 2);
+ return;
+ }
+
+ // there is no need to check, whether or not the character was
+ // queued for deletion, as the client prints an error message by
+ // itself, if it was not the case (@see char_delete2_cancel_ack)
+ if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='0' WHERE `char_id`='%d'", char_db, char_id) )
+ {
+ Sql_ShowDebug(sql_handle);
+ char_delete2_cancel_ack(fd, char_id, 2);
+ return;
+ }
+
+ char_delete2_cancel_ack(fd, char_id, 1);
+}
+
+
int parse_char(int fd)
{
int i, ch;
@@ -3393,6 +3622,27 @@ int parse_char(int fd)
RFIFOSKIP(fd,32);
break;
+ // deletion timer request
+ case 0x827:
+ FIFOSD_CHECK(6);
+ char_delete2_req(fd, sd);
+ RFIFOSKIP(fd,6);
+ break;
+
+ // deletion accept request
+ case 0x829:
+ FIFOSD_CHECK(12);
+ char_delete2_accept(fd, sd);
+ RFIFOSKIP(fd,12);
+ break;
+
+ // deletion cancel request
+ case 0x82b:
+ FIFOSD_CHECK(6);
+ char_delete2_cancel(fd, sd);
+ RFIFOSKIP(fd,6);
+ break;
+
// login as map-server
case 0x2af8:
if (RFIFOREST(fd) < 60)
@@ -3910,6 +4160,8 @@ int char_config_read(const char* cfgName)
char_per_account = atoi(w2);
} else if (strcmpi(w1, "char_del_level") == 0) { //disable/enable char deletion by its level condition [Lupus]
char_del_level = atoi(w2);
+ } else if (strcmpi(w1, "char_del_delay") == 0) {
+ char_del_delay = atoi(w2);
} else if(strcmpi(w1,"db_path")==0) {
safestrncpy(db_path, w2, sizeof(db_path));
} else if (strcmpi(w1, "console") == 0) {
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 92adf8af0..39a5717ab 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -38,6 +38,7 @@
// 20100629 - 2010-06-29aRagexeRE+ - 0x2d0, 0xaa, 0x2d1, 0x2d2
// 20100721 - 2010-07-21aRagexeRE+ - 0x6b, 0x6d
// 20100727 - 2010-07-27aRagexeRE+ - 0x6b, 0x6d
+// 20100803 - 2010-08-03aRagexeRE+ - 0x6b, 0x6d, 0x827, 0x828, 0x829, 0x82a, 0x82b, 0x82c, 0x842, 0x843
#ifndef PACKETVER
#define PACKETVER 20081126
@@ -53,8 +54,6 @@
#define PACKETVER 20071106
#endif
-#define FIFOSIZE_SERVERLINK 256*1024
-
//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]
@@ -85,7 +84,7 @@
#define MAX_ZENY 1000000000
#define MAX_FAME 1000000000
#define MAX_CART 100
-#define MAX_SKILL 1020
+#define MAX_SKILL 2536
#define GLOBAL_REG_NUM 256
#define ACCOUNT_REG_NUM 64
#define ACCOUNT_REG2_NUM 16
@@ -95,7 +94,7 @@
#define MIN_WALK_SPEED 0
#define MAX_WALK_SPEED 1000
#define MAX_STORAGE 600
-#define MAX_GUILD_STORAGE 1000
+#define MAX_GUILD_STORAGE 600
#define MAX_PARTY 12
#define MAX_GUILD 16+10*6 // increased max guild members +6 per 1 extension levels [Lupus]
#define MAX_GUILDPOSITION 20 // increased max guild positions to accomodate for all members [Valaris] (removed) [PoW]
@@ -350,6 +349,8 @@ struct mmo_charstatus {
#endif
bool show_equip;
short rename;
+
+ time_t delete_date;
};
typedef enum mail_status {
diff --git a/src/common/socket.c b/src/common/socket.c
index ff667cf2e..0a576e517 100644
--- a/src/common/socket.c
+++ b/src/common/socket.c
@@ -543,18 +543,16 @@ static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseF
return 0;
}
-static int delete_session(int fd)
+static void delete_session(int fd)
{
- if (fd <= 0 || fd >= FD_SETSIZE)
- return -1;
- if (session[fd]) {
+ if( session_isValid(fd) )
+ {
aFree(session[fd]->rdata);
aFree(session[fd]->wdata);
aFree(session[fd]->session_data);
aFree(session[fd]);
session[fd] = NULL;
}
- return 0;
}
int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size)
@@ -584,7 +582,7 @@ int realloc_writefifo(int fd, size_t addition)
if( session[fd]->wdata_size + addition > session[fd]->max_wdata )
{ // grow rule; grow in multiples of WFIFO_SIZE
newsize = WFIFO_SIZE;
- while( session[fd]->wdata_size + addition > newsize ) newsize += newsize;
+ while( session[fd]->wdata_size + addition > newsize ) newsize += WFIFO_SIZE;
}
else
if( session[fd]->max_wdata >= (size_t)2*(session[fd]->flag.server?FIFOSIZE_SERVERLINK:WFIFO_SIZE)
@@ -667,9 +665,9 @@ int WFIFOSET(int fd, size_t len)
// always keep a WFIFO_SIZE reserve in the buffer
// For inter-server connections, let the reserve be 1/4th of the link size.
- newreserve = s->wdata_size + ( s->flag.server ? FIFOSIZE_SERVERLINK / 4 : WFIFO_SIZE);
+ newreserve = s->flag.server ? FIFOSIZE_SERVERLINK / 4 : WFIFO_SIZE;
- // readjust the buffer to the newly chosen size
+ // readjust the buffer to include the chosen reserve
realloc_writefifo(fd, newreserve);
#ifdef SEND_SHORTLIST
@@ -1333,10 +1331,12 @@ void send_shortlist_add_fd(int fd)
int i;
int bit;
- if( fd < 0 || fd >= FD_SETSIZE )
+ if( !session_isValid(fd) )
return;// out of range
+
i = fd/32;
bit = fd%32;
+
if( (send_shortlist_set[i]>>bit)&1 )
return;// already in the list
diff --git a/src/common/socket.h b/src/common/socket.h
index 0a740a63f..2f0ec6081 100644
--- a/src/common/socket.h
+++ b/src/common/socket.h
@@ -9,6 +9,7 @@
#endif
#ifdef WIN32
+ #define WIN32_LEAN_AND_MEAN // otherwise winsock2.h includes full windows.h
#include <winsock2.h>
typedef long in_addr_t;
#else
@@ -19,6 +20,7 @@
#include <time.h>
+#define FIFOSIZE_SERVERLINK 256*1024
// socket I/O macros
#define RFIFOHEAD(fd)
diff --git a/src/common/strlib.c b/src/common/strlib.c
index a0cba906c..66f281ffc 100644
--- a/src/common/strlib.c
+++ b/src/common/strlib.c
@@ -8,7 +8,6 @@
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <errno.h>
@@ -241,7 +240,7 @@ char* _strtok_r(char *s1, const char *s2, char **lasts)
}
#endif
-#if !(defined(WIN32) && defined(_MSC_VER) && _MSC_VER >= 1400) && !defined(CYGWIN)
+#if !(defined(WIN32) && defined(_MSC_VER) && _MSC_VER >= 1400) && !defined(HAVE_STRNLEN)
/* Find the length of STRING, but scan at most MAXLEN characters.
If no '\0' terminator is found in that many characters, return MAXLEN. */
size_t strnlen (const char* string, size_t maxlen)
diff --git a/src/common/strlib.h b/src/common/strlib.h
index 23f1e191a..3f4f984cf 100644
--- a/src/common/strlib.h
+++ b/src/common/strlib.h
@@ -9,6 +9,10 @@
#endif
#include <stdarg.h>
+#define __USE_GNU // required to enable strnlen on some platforms
+#include <string.h>
+#undef __USE_GNU
+
char* jstrescape (char* pt);
char* jstrescapecpy (char* pt, const char* spt);
int jmemescapecpy (char* pt, const char* spt, int size);
@@ -24,7 +28,7 @@ const char *stristr(const char *haystack, const char *needle);
char* _strtok_r(char* s1, const char* s2, char** lasts);
#endif
-#if !(defined(WIN32) && defined(_MSC_VER) && _MSC_VER >= 1400) && !defined(CYGWIN)
+#if !(defined(WIN32) && defined(_MSC_VER) && _MSC_VER >= 1400) && !defined(HAVE_STRNLEN)
size_t strnlen (const char* string, size_t maxlen);
#endif
diff --git a/src/common/utils.c b/src/common/utils.c
index 12123784f..f1813ea41 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -5,6 +5,7 @@
#include "../common/mmo.h"
#include "../common/malloc.h"
#include "../common/showmsg.h"
+#include "socket.h"
#include "utils.h"
#include <stdio.h>
@@ -25,39 +26,64 @@
#include <sys/stat.h>
#endif
-// generate a hex dump of the first 'length' bytes of 'buffer'
-void dump(FILE* fp, const unsigned char* buffer, int length)
+
+/// Dumps given buffer into file pointed to by a handle.
+void WriteDump(FILE* fp, const void* buffer, size_t length)
{
- int i, j;
+ size_t i;
+ char hex[48+1], ascii[16+1];
- fprintf(fp, " Hex ASCII\n");
- fprintf(fp, " ----------------------------------------------- ----------------");
+ fprintf(fp, "--- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F 0123456789ABCDEF\n");
+ ascii[16] = 0;
- for (i = 0; i < length; i += 16)
+ for( i = 0; i < length; i++ )
{
- fprintf(fp, "\n%p ", &buffer[i]);
- for (j = i; j < i + 16; ++j)
+ char c = RBUFB(buffer,i);
+
+ ascii[i%16] = ISCNTRL(c) ? '.' : c;
+ sprintf(hex+(i%16)*3, "%02X ", RBUFB(buffer,i));
+
+ if( (i%16) == 15 )
{
- if (j < length)
- fprintf(fp, "%02hX ", buffer[j]);
- else
- fprintf(fp, " ");
+ fprintf(fp, "%03X %s %s\n", i/16, hex, ascii);
}
+ }
+
+ if( (i%16) != 0 )
+ {
+ ascii[i%16] = 0;
+ fprintf(fp, "%03X %-48s %-16s\n", i/16, hex, ascii);
+ }
+}
+
- fprintf(fp, " | ");
+/// Dumps given buffer on the console.
+void ShowDump(const void* buffer, size_t length)
+{
+ size_t i;
+ char hex[48+1], ascii[16+1];
+
+ ShowDebug("--- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F 0123456789ABCDEF\n");
+ ascii[16] = 0;
+
+ for( i = 0; i < length; i++ )
+ {
+ char c = RBUFB(buffer,i);
+
+ ascii[i%16] = ISCNTRL(c) ? '.' : c;
+ sprintf(hex+(i%16)*3, "%02X ", RBUFB(buffer,i));
- for (j = i; j < i + 16; ++j)
+ if( (i%16) == 15 )
{
- if (j < length) {
- if (buffer[j] > 31 && buffer[j] < 127)
- fprintf(fp, "%c", buffer[j]);
- else
- fprintf(fp, ".");
- } else
- fprintf(fp, " ");
+ ShowDebug("%03X %s %s\n", i/16, hex, ascii);
}
}
- fprintf(fp, "\n");
+
+ if( (i%16) != 0 )
+ {
+ ascii[i%16] = 0;
+ ShowDebug("%03X %-48s %-16s\n", i/16, hex, ascii);
+ }
}
@@ -183,6 +209,8 @@ void findfile(const char *p, const char *pat, void (func)(const char*))
findfile(tmppath, pat, func);
}
}//end while
+
+ closedir(dir);
}
#endif
diff --git a/src/common/utils.h b/src/common/utils.h
index 5cf3ff3cf..2fe078615 100644
--- a/src/common/utils.h
+++ b/src/common/utils.h
@@ -11,7 +11,8 @@
#include <stdio.h> // FILE*
// generate a hex dump of the first 'length' bytes of 'buffer'
-void dump(FILE* fp, const unsigned char* buffer, int length);
+void WriteDump(FILE* fp, const void* buffer, size_t length);
+void ShowDump(const void* buffer, size_t length);
void findfile(const char *p, const char *pat, void (func)(const char*));
bool exists(const char* filename);
diff --git a/src/login/account_sql.c b/src/login/account_sql.c
index e3e725efa..be1b36ebe 100644
--- a/src/login/account_sql.c
+++ b/src/login/account_sql.c
@@ -12,7 +12,7 @@
#include <string.h>
/// global defines
-#define ACCOUNT_SQL_DB_VERSION 20080417
+#define ACCOUNT_SQL_DB_VERSION 20110114
/// internal structure
typedef struct AccountDB_SQL
diff --git a/src/login/login.c b/src/login/login.c
index 6a8525930..6d8043baf 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -517,6 +517,7 @@ int parse_fromchar(int fd)
time_t expiration_time = 0;
char email[40] = "";
int gmlevel = 0;
+ char birthdate[10+1] = "";
int account_id = RFIFOL(fd,2);
RFIFOSKIP(fd,6);
@@ -528,15 +529,17 @@ int parse_fromchar(int fd)
safestrncpy(email, acc.email, sizeof(email));
expiration_time = acc.expiration_time;
gmlevel = acc.level;
+ safestrncpy(birthdate, acc.birthdate, sizeof(birthdate));
}
- WFIFOHEAD(fd,51);
+ WFIFOHEAD(fd,62);
WFIFOW(fd,0) = 0x2717;
WFIFOL(fd,2) = account_id;
safestrncpy((char*)WFIFOP(fd,6), email, 40);
WFIFOL(fd,46) = (uint32)expiration_time;
WFIFOB(fd,50) = gmlevel;
- WFIFOSET(fd,51);
+ safestrncpy((char*)WFIFOP(fd,51), birthdate, 10+1);
+ WFIFOSET(fd,62);
}
break;
diff --git a/src/map/Makefile.in b/src/map/Makefile.in
index cf6a29d6c..f45f4dd00 100644
--- a/src/map/Makefile.in
+++ b/src/map/Makefile.in
@@ -17,7 +17,8 @@ MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \
npc_chat.o chat.o path.o itemdb.o mob.o script.o \
storage.o skill.o atcommand.o battle.o battleground.o \
intif.o trade.o party.o vending.o guild.o pet.o \
- log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o
+ log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o \
+ buyingstore.o searchstore.o
MAP_TXT_OBJ = $(MAP_OBJ:%=obj_txt/%) \
obj_txt/mapreg_txt.o
MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) \
@@ -26,7 +27,8 @@ MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \
chat.h itemdb.h mob.h script.h path.h \
storage.h skill.h atcommand.h battle.h battleground.h \
intif.h trade.h party.h vending.h guild.h pet.h \
- log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h
+ log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h \
+ buyingstore.h searchstore.h
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index cebd881ce..b44eae946 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -1150,7 +1150,7 @@ ACMD_FUNC(storage)
{
nullpo_retr(-1, sd);
- if (sd->npc_id || sd->vender_id || sd->state.trading || sd->state.storage_flag)
+ if (sd->npc_id || sd->vender_id || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag)
return -1;
if (storage_storageopen(sd) == 1)
@@ -1177,7 +1177,7 @@ ACMD_FUNC(guildstorage)
return -1;
}
- if (sd->npc_id || sd->vender_id || sd->state.trading)
+ if (sd->npc_id || sd->vender_id || sd->state.buyingstore || sd->state.trading)
return -1;
if (sd->state.storage_flag == 1) {
@@ -1673,8 +1673,8 @@ ACMD_FUNC(item2)
}
if (item_data->type == IT_PETARMOR)
refine = 0;
- if (refine > 10)
- refine = 10;
+ if (refine > MAX_REFINE)
+ refine = MAX_REFINE;
} else {
identify = 1;
refine = attr = 0;
@@ -1956,7 +1956,7 @@ ACMD_FUNC(pvpoff)
map[sd->bl.m].flag.pvp = 0;
if (!battle_config.pk_mode)
- clif_send0199(sd->bl.m, 0);
+ clif_map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING);
map_foreachinmap(atcommand_pvpoff_sub,sd->bl.m, BL_PC);
map_foreachinmap(atcommand_stopattack,sd->bl.m, BL_CHAR, 0);
clif_displaymessage(fd, msg_txt(31)); // PvP: Off.
@@ -1993,7 +1993,7 @@ ACMD_FUNC(pvpon)
if (!battle_config.pk_mode)
{// display pvp circle and rank
- clif_send0199(sd->bl.m, 1);
+ clif_map_property_mapall(sd->bl.m, MAPPROPERTY_FREEPVPZONE);
map_foreachinmap(atcommand_pvpon_sub,sd->bl.m, BL_PC);
}
@@ -2015,7 +2015,7 @@ ACMD_FUNC(gvgoff)
}
map[sd->bl.m].flag.gvg = 0;
- clif_send0199(sd->bl.m, 0);
+ clif_map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING);
map_foreachinmap(atcommand_stopattack,sd->bl.m, BL_CHAR, 0);
clif_displaymessage(fd, msg_txt(33)); // GvG: Off.
@@ -2035,7 +2035,7 @@ ACMD_FUNC(gvgon)
}
map[sd->bl.m].flag.gvg = 1;
- clif_send0199(sd->bl.m, 3);
+ clif_map_property_mapall(sd->bl.m, MAPPROPERTY_AGITZONE);
clif_displaymessage(fd, msg_txt(34)); // GvG: On.
return 0;
@@ -3009,7 +3009,7 @@ ACMD_FUNC(param)
status[4] = &sd->status.dex;
status[5] = &sd->status.luk;
- if(value < 0 && *status[i] < -value)
+ if(value < 0 && *status[i] <= -value)
{
new_value = 1;
}
@@ -5945,8 +5945,8 @@ ACMD_FUNC(autotrade)
return -1;
}
- if( !sd->vender_id ) { //check if player is vending
- clif_displaymessage(fd, msg_txt(549)); // You should be vending to use @Autotrade.
+ if( !sd->vender_id && !sd->state.buyingstore ) { //check if player is vending or buying
+ clif_displaymessage(fd, msg_txt(549)); // "You should have a shop open to use @autotrade."
return -1;
}
diff --git a/src/map/battle.c b/src/map/battle.c
index 3e58c1209..f60be479a 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -4006,6 +4006,12 @@ static const struct _battle_data {
{ "autospell_check_range", &battle_config.autospell_check_range, 0, 0, 1, },
{ "client_reshuffle_dice", &battle_config.client_reshuffle_dice, 0, 0, 1, },
{ "client_sort_storage", &battle_config.client_sort_storage, 0, 0, 1, },
+ { "gm_check_minlevel", &battle_config.gm_check_minlevel, 60, 0, 100, },
+ { "feature.buying_store", &battle_config.feature_buying_store, 1, 0, 1, },
+ { "feature.search_stores", &battle_config.feature_search_stores, 1, 0, 1, },
+ { "searchstore_querydelay", &battle_config.searchstore_querydelay, 10, 0, INT_MAX, },
+ { "searchstore_maxresults", &battle_config.searchstore_maxresults, 30, 1, INT_MAX, },
+ { "display_party_name", &battle_config.display_party_name, 0, 0, 1, },
// BattleGround Settings
{ "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, },
{ "bg_short_attack_damage_rate", &battle_config.bg_short_damage_rate, 80, 0, INT_MAX, },
diff --git a/src/map/battle.h b/src/map/battle.h
index 3abc6b0a4..b2f33b73b 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -480,6 +480,12 @@ extern struct Battle_Config
int autospell_check_range; //Enable range check for autospell bonus. [L0ne_W0lf]
int client_reshuffle_dice; // Reshuffle /dice
int client_sort_storage;
+ int gm_check_minlevel; // min GM level for /check
+ int feature_buying_store;
+ int feature_search_stores;
+ int searchstore_querydelay;
+ int searchstore_maxresults;
+ int display_party_name;
// [BattleGround Settings]
int bg_update_interval;
diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c
new file mode 100644
index 000000000..8f158cd29
--- /dev/null
+++ b/src/map/buyingstore.c
@@ -0,0 +1,470 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/cbasetypes.h"
+#include "../common/db.h" // ARR_FIND
+#include "../common/showmsg.h" // ShowWarning
+#include "../common/socket.h" // RBUF*
+#include "../common/strlib.h" // safestrncpy
+#include "atcommand.h" // msg_txt
+#include "battle.h" // battle_config.*
+#include "buyingstore.h" // struct s_buyingstore
+#include "clif.h" // clif_buyingstore_*
+#include "log.h" // log_pick_pc, log_zeny
+#include "pc.h" // struct map_session_data
+
+
+/// constants (client-side restrictions)
+#define BUYINGSTORE_MAX_PRICE 99990000
+#define BUYINGSTORE_MAX_AMOUNT 9999
+
+
+/// failure constants for clif functions
+enum e_buyingstore_failure
+{
+ BUYINGSTORE_CREATE = 1, // "Failed to open buying store."
+ BUYINGSTORE_CREATE_OVERWEIGHT = 2, // "Total amount of then possessed items exceeds the weight limit by %d. Please re-enter."
+ BUYINGSTORE_TRADE_BUYER_ZENY = 3, // "All items within the buy limit were purchased."
+ BUYINGSTORE_TRADE_BUYER_NO_ITEMS = 4, // "All items were purchased."
+ BUYINGSTORE_TRADE_SELLER_FAILED = 5, // "The deal has failed."
+ BUYINGSTORE_TRADE_SELLER_COUNT = 6, // "The trade failed, because the entered amount of item %s is higher, than the buyer is willing to buy."
+ BUYINGSTORE_TRADE_SELLER_ZENY = 7, // "The trade failed, because the buyer is lacking required balance."
+ BUYINGSTORE_CREATE_NO_INFO = 8, // "No sale (purchase) information available."
+};
+
+
+static unsigned int buyingstore_nextid = 0;
+static const short buyingstore_blankslots[MAX_SLOTS] = { 0 }; // used when checking whether or not an item's card slots are blank
+
+
+/// Returns unique buying store id
+static unsigned int buyingstore_getuid(void)
+{
+ return buyingstore_nextid++;
+}
+
+
+bool buyingstore_setup(struct map_session_data* sd, unsigned char slots)
+{
+ if( !battle_config.feature_buying_store || sd->vender_id || sd->state.buyingstore || sd->state.trading || slots == 0 )
+ {
+ return false;
+ }
+
+ if( sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) )
+ {// custom: mute limitation
+ return false;
+ }
+
+ if( map[sd->bl.m].flag.novending || map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) )
+ {// custom: no vending maps/cells
+ clif_displaymessage(sd->fd, msg_txt(276)); // "You can't open a shop on this map"
+ return false;
+ }
+
+ if( slots > MAX_BUYINGSTORE_SLOTS )
+ {
+ ShowWarning("buyingstore_setup: Requested %d slots, but server supports only %d slots.\n", (int)slots, MAX_BUYINGSTORE_SLOTS);
+ slots = MAX_BUYINGSTORE_SLOTS;
+ }
+
+ sd->buyingstore.slots = slots;
+ clif_buyingstore_open(sd);
+
+ return true;
+}
+
+
+void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count)
+{
+ unsigned int i, weight, listidx;
+ struct item_data* id;
+
+ if( !result || count == 0 )
+ {// canceled, or no items
+ return;
+ }
+
+ if( !battle_config.feature_buying_store || pc_istrading(sd) || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0] )
+ {// disabled or invalid input
+ sd->buyingstore.slots = 0;
+ clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
+ return;
+ }
+
+ if( !pc_can_give_items(pc_isGM(sd)) )
+ {// custom: GM is not allowed to buy (give zeny)
+ sd->buyingstore.slots = 0;
+ clif_displaymessage(sd->fd, msg_txt(246));
+ clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
+ return;
+ }
+
+ if( sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) )
+ {// custom: mute limitation
+ return;
+ }
+
+ if( map[sd->bl.m].flag.novending || map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) )
+ {// custom: no vending maps/cells
+ clif_displaymessage(sd->fd, msg_txt(276)); // "You can't open a shop on this map"
+ return;
+ }
+
+ weight = sd->weight;
+
+ // check item list
+ for( i = 0; i < count; i++ )
+ {// itemlist: <name id>.W <amount>.W <price>.L
+ unsigned short nameid, amount;
+ int price, idx;
+
+ nameid = RBUFW(itemlist,i*8+0);
+ amount = RBUFW(itemlist,i*8+2);
+ price = RBUFL(itemlist,i*8+4);
+
+ if( ( id = itemdb_exists(nameid) ) == NULL || amount == 0 )
+ {// invalid input
+ break;
+ }
+
+ if( price <= 0 || price > BUYINGSTORE_MAX_PRICE )
+ {// invalid price: unlike vending, items cannot be bought at 0 Zeny
+ break;
+ }
+
+ if( !id->flag.buyingstore || !itemdb_cantrade_sub(id, pc_isGM(sd), pc_isGM(sd)) || ( idx = pc_search_inventory(sd, nameid) ) == -1 )
+ {// restrictions: allowed, no character-bound items and at least one must be owned
+ break;
+ }
+
+ if( sd->status.inventory[idx].amount+amount > BUYINGSTORE_MAX_AMOUNT )
+ {// too many items of same kind
+ break;
+ }
+
+ if( i )
+ {// duplicate check. as the client does this too, only malicious intent should be caught here
+ ARR_FIND( 0, i, listidx, sd->buyingstore.items[i].nameid == nameid );
+ if( listidx != i )
+ {// duplicate
+ ShowWarning("buyingstore_create: Found duplicate item on buying list (nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", nameid, amount, sd->status.account_id, sd->status.char_id);
+ break;
+ }
+ }
+
+ weight+= id->weight*amount;
+ sd->buyingstore.items[i].nameid = nameid;
+ sd->buyingstore.items[i].amount = amount;
+ sd->buyingstore.items[i].price = price;
+ }
+
+ if( i != count )
+ {// invalid item/amount/price
+ sd->buyingstore.slots = 0;
+ clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
+ return;
+ }
+
+ if( (sd->max_weight*90)/100 < weight )
+ {// not able to carry all wanted items without getting overweight (90%)
+ sd->buyingstore.slots = 0;
+ clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight);
+ return;
+ }
+
+ // success
+ sd->state.buyingstore = true;
+ sd->buyer_id = buyingstore_getuid();
+ sd->buyingstore.zenylimit = zenylimit;
+ sd->buyingstore.slots = i; // store actual amount of items
+ safestrncpy(sd->message, storename, sizeof(sd->message));
+ clif_buyingstore_myitemlist(sd);
+ clif_buyingstore_entry(sd);
+}
+
+
+void buyingstore_close(struct map_session_data* sd)
+{
+ if( sd->state.buyingstore )
+ {
+ // invalidate data
+ sd->state.buyingstore = false;
+ memset(&sd->buyingstore, 0, sizeof(sd->buyingstore));
+
+ // notify other players
+ clif_buyingstore_disappear_entry(sd);
+ }
+}
+
+
+void buyingstore_open(struct map_session_data* sd, int account_id)
+{
+ struct map_session_data* pl_sd;
+
+ if( !battle_config.feature_buying_store || pc_istrading(sd) )
+ {// not allowed to sell
+ return;
+ }
+
+ if( !pc_can_give_items(pc_isGM(sd)) )
+ {// custom: GM is not allowed to sell
+ clif_displaymessage(sd->fd, msg_txt(246));
+ return;
+ }
+
+ if( ( pl_sd = map_id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore )
+ {// not online or not buying
+ return;
+ }
+
+ if( !searchstore_queryremote(sd, account_id) && ( sd->bl.m != pl_sd->bl.m || !check_distance_bl(&sd->bl, &pl_sd->bl, AREA_SIZE) ) )
+ {// out of view range
+ return;
+ }
+
+ // success
+ clif_buyingstore_itemlist(sd, pl_sd);
+}
+
+
+void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count)
+{
+ int zeny = 0;
+ unsigned int i, weight, listidx, k;
+ struct map_session_data* pl_sd;
+
+ if( count == 0 )
+ {// nothing to do
+ return;
+ }
+
+ if( !battle_config.feature_buying_store || pc_istrading(sd) )
+ {// not allowed to sell
+ clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
+ return;
+ }
+
+ if( !pc_can_give_items(pc_isGM(sd)) )
+ {// custom: GM is not allowed to sell
+ clif_displaymessage(sd->fd, msg_txt(246));
+ clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
+ return;
+ }
+
+ if( ( pl_sd = map_id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore || pl_sd->buyer_id != buyer_id )
+ {// not online, not buying or not same store
+ clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
+ return;
+ }
+
+ if( !searchstore_queryremote(sd, account_id) && ( sd->bl.m != pl_sd->bl.m || !check_distance_bl(&sd->bl, &pl_sd->bl, AREA_SIZE) ) )
+ {// out of view range
+ clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
+ return;
+ }
+
+ searchstore_clearremote(sd);
+
+ if( pl_sd->status.zeny < pl_sd->buyingstore.zenylimit )
+ {// buyer lost zeny in the mean time? fix the limit
+ pl_sd->buyingstore.zenylimit = pl_sd->status.zeny;
+ }
+ weight = pl_sd->weight;
+
+ // check item list
+ for( i = 0; i < count; i++ )
+ {// itemlist: <index>.W <name id>.W <amount>.W
+ unsigned short nameid, amount;
+ int index;
+
+ index = RBUFW(itemlist,i*6+0)-2;
+ nameid = RBUFW(itemlist,i*6+2);
+ amount = RBUFW(itemlist,i*6+4);
+
+ if( i )
+ {// duplicate check. as the client does this too, only malicious intent should be caught here
+ ARR_FIND( 0, i, k, RBUFW(itemlist,k*6+0)-2 == index );
+ if( k != i )
+ {// duplicate
+ ShowWarning("buyingstore_trade: Found duplicate item on selling list (prevnameid=%hu, prevamount=%hu, nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n",
+ RBUFW(itemlist,k*6+2), RBUFW(itemlist,k*6+4), nameid, amount, sd->status.account_id, sd->status.char_id);
+ clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
+ return;
+ }
+ }
+
+ if( index < 0 || index >= ARRAYLENGTH(sd->status.inventory) || sd->inventory_data[index] == NULL || sd->status.inventory[index].nameid != nameid || sd->status.inventory[index].amount < amount )
+ {// invalid input
+ clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
+ return;
+ }
+
+ if( sd->status.inventory[index].expire_time || !itemdb_cantrade(&sd->status.inventory[index], pc_isGM(sd), pc_isGM(pl_sd)) || memcmp(sd->status.inventory[index].card, buyingstore_blankslots, sizeof(buyingstore_blankslots)) )
+ {// non-tradable item
+ clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
+ return;
+ }
+
+ ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid );
+ if( listidx == pl_sd->buyingstore.slots || pl_sd->buyingstore.items[listidx].amount == 0 )
+ {// there is no such item or the buyer has already bought all of them
+ clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
+ return;
+ }
+
+ if( pl_sd->buyingstore.items[listidx].amount < amount )
+ {// buyer does not need that much of the item
+ clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_COUNT, nameid);
+ return;
+ }
+
+ if( pc_checkadditem(pl_sd, nameid, amount) == ADDITEM_OVERAMOUNT )
+ {// buyer does not have enough space for this item
+ clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
+ return;
+ }
+
+ if( amount*(unsigned int)sd->inventory_data[index]->weight > pl_sd->max_weight-weight )
+ {// normally this is not supposed to happen, as the total weight is
+ // checked upon creation, but the buyer could have gained items
+ clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
+ return;
+ }
+ weight+= amount*sd->inventory_data[index]->weight;
+
+ if( amount*pl_sd->buyingstore.items[listidx].price > pl_sd->buyingstore.zenylimit-zeny )
+ {// buyer does not have enough zeny
+ clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_ZENY, nameid);
+ return;
+ }
+ zeny+= amount*pl_sd->buyingstore.items[listidx].price;
+ }
+
+ // process item list
+ for( i = 0; i < count; i++ )
+ {// itemlist: <index>.W <name id>.W <amount>.W
+ unsigned short nameid, amount;
+ int index;
+
+ index = RBUFW(itemlist,i*6+0)-2;
+ nameid = RBUFW(itemlist,i*6+2);
+ amount = RBUFW(itemlist,i*6+4);
+
+ ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid );
+ zeny = amount*pl_sd->buyingstore.items[listidx].price;
+
+ // log
+ if( log_config.enable_logs&LOG_BUYING_STORE )
+ {
+ log_pick_pc(sd, "B", nameid, -((int)amount), &sd->status.inventory[index]);
+ log_pick_pc(pl_sd, "B", nameid, amount, &sd->status.inventory[index]);
+ }
+ if( log_config.zeny )
+ log_zeny(sd, "B", pl_sd, zeny);
+
+ // move item
+ pc_additem(pl_sd, &sd->status.inventory[index], amount);
+ pc_delitem(sd, index, amount, 1, 0);
+ pl_sd->buyingstore.items[listidx].amount-= amount;
+
+ // pay up
+ pc_payzeny(pl_sd, zeny);
+ pc_getzeny(sd, zeny);
+ pl_sd->buyingstore.zenylimit-= zeny;
+
+ // notify clients
+ clif_buyingstore_delete_item(sd, index, amount, pl_sd->buyingstore.items[listidx].price);
+ clif_buyingstore_update_item(pl_sd, nameid, amount);
+ }
+
+ // check whether or not there is still something to buy
+ ARR_FIND( 0, pl_sd->buyingstore.slots, i, pl_sd->buyingstore.items[i].amount != 0 );
+ if( i == pl_sd->buyingstore.slots )
+ {// everything was bought
+ clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_NO_ITEMS);
+ }
+ else if( pl_sd->buyingstore.zenylimit == 0 )
+ {// zeny limit reached
+ clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_ZENY);
+ }
+ else
+ {// continue buying
+ return;
+ }
+
+ // cannot continue buying
+ buyingstore_close(pl_sd);
+
+ // remove auto-trader
+ if( pl_sd->state.autotrade )
+ {
+ map_quit(pl_sd);
+ }
+}
+
+
+/// Checks if an item is being bought in given player's buying store.
+bool buyingstore_search(struct map_session_data* sd, unsigned short nameid)
+{
+ unsigned int i;
+
+ if( !sd->state.buyingstore )
+ {// not buying
+ return false;
+ }
+
+ ARR_FIND( 0, sd->buyingstore.slots, i, sd->buyingstore.items[i].nameid == nameid && sd->buyingstore.items[i].amount );
+ if( i == sd->buyingstore.slots )
+ {// not found
+ return false;
+ }
+
+ return true;
+}
+
+
+/// Searches for all items in a buyingstore, that match given ids, price and possible cards.
+/// @return Whether or not the search should be continued.
+bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_store_search* s)
+{
+ unsigned int i, idx;
+ struct s_buyingstore_item* it;
+
+ if( !sd->state.buyingstore )
+ {// not buying
+ return true;
+ }
+
+ for( idx = 0; idx < s->item_count; idx++ )
+ {
+ ARR_FIND( 0, sd->buyingstore.slots, i, sd->buyingstore.items[i].nameid == s->itemlist[idx] && sd->buyingstore.items[i].amount );
+ if( i == sd->buyingstore.slots )
+ {// not found
+ continue;
+ }
+ it = &sd->buyingstore.items[i];
+
+ if( s->min_price && s->min_price > (unsigned int)it->price )
+ {// too low price
+ continue;
+ }
+
+ if( s->max_price && s->max_price < (unsigned int)it->price )
+ {// too high price
+ continue;
+ }
+
+ if( s->card_count )
+ {// ignore cards, as there cannot be any
+ ;
+ }
+
+ if( !searchstore_result(s->search_sd, sd->buyer_id, sd->status.account_id, sd->message, it->nameid, it->amount, it->price, buyingstore_blankslots, 0) )
+ {// result set full
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/src/map/buyingstore.h b/src/map/buyingstore.h
new file mode 100644
index 000000000..0ed6e5457
--- /dev/null
+++ b/src/map/buyingstore.h
@@ -0,0 +1,33 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef _BUYINGSTORE_H_
+#define _BUYINGSTORE_H_
+
+struct s_search_store_search;
+
+#define MAX_BUYINGSTORE_SLOTS 5
+
+struct s_buyingstore_item
+{
+ int price;
+ unsigned short amount;
+ unsigned short nameid;
+};
+
+struct s_buyingstore
+{
+ struct s_buyingstore_item items[MAX_BUYINGSTORE_SLOTS];
+ int zenylimit;
+ unsigned char slots;
+};
+
+bool buyingstore_setup(struct map_session_data* sd, unsigned char slots);
+void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count);
+void buyingstore_close(struct map_session_data* sd);
+void buyingstore_open(struct map_session_data* sd, int account_id);
+void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count);
+bool buyingstore_search(struct map_session_data* sd, unsigned short nameid);
+bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_store_search* s);
+
+#endif // _BUYINGSTORE_H_
diff --git a/src/map/chat.c b/src/map/chat.c
index 96ec4c20d..4ba784b2e 100644
--- a/src/map/chat.c
+++ b/src/map/chat.c
@@ -69,6 +69,11 @@ int chat_createpcchat(struct map_session_data* sd, const char* title, const char
if( sd->chatID )
return 0; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex]
+ if( sd->vender_id || sd->state.buyingstore )
+ {// not chat, when you already have a store open
+ return 0;
+ }
+
if( map[sd->bl.m].flag.nochat )
{
clif_displaymessage(sd->fd, msg_txt(281));
@@ -108,7 +113,7 @@ int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass)
nullpo_ret(sd);
cd = (struct chat_data*)map_id2bl(chatid);
- if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->vender_id || sd->chatID || cd->users >= cd->limit )
+ if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->vender_id || sd->state.buyingstore || sd->chatID || cd->users >= cd->limit )
{
clif_joinchatfail(sd,0);
return 0;
diff --git a/src/map/clif.c b/src/map/clif.c
index b724ddbab..960a63c0e 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -46,7 +46,8 @@
#include <stdarg.h>
#include <time.h>
-#define DUMP_UNKNOWN_PACKET 0
+//#define DUMP_UNKNOWN_PACKET
+//#define DUMP_INVALID_PACKET
struct Clif_Config {
int packet_db_ver; //Preferred packet version.
@@ -56,7 +57,10 @@ struct Clif_Config {
struct s_packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB + 1];
//Converts item type in case of pet eggs.
-#define itemtype(a) (a == IT_PETEGG)?IT_WEAPON:a
+inline int itemtype(int type)
+{
+ return ( type == IT_PETEGG ) ? IT_WEAPON : type;
+}
#define WBUFPOS(p,pos,x,y,dir) \
do { \
@@ -1216,7 +1220,7 @@ int clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag)
WBUFL(buf,59)=hd->homunculus.exp;
WBUFL(buf,63)=hd->exp_next;
WBUFW(buf,67)=hd->homunculus.skillpts;
- WBUFW(buf,69)=2; // FIXME: undocumented flag, seems to be '2' all the time [ultramage]
+ WBUFW(buf,69)=status_get_range(&hd->bl);
clif_send(buf,packet_len(0x22e),&sd->bl,SELF);
return 0;
}
@@ -1227,7 +1231,7 @@ void clif_send_homdata(struct map_session_data *sd, int type, int param)
WFIFOHEAD(fd, packet_len(0x230));
nullpo_retv(sd->hd);
WFIFOW(fd,0)=0x230;
- WFIFOW(fd,2)=type;
+ WFIFOW(fd,2)=type; // FIXME: This is actually <type>.B <state>.B
WFIFOL(fd,4)=sd->hd->bl.id;
WFIFOL(fd,8)=param;
WFIFOSET(fd,packet_len(0x230));
@@ -2815,8 +2819,8 @@ int clif_initialstatus(struct map_session_data *sd)
WBUFW(buf,34) = sd->battle_status.flee;
WBUFW(buf,36) = sd->battle_status.flee2/10;
WBUFW(buf,38) = sd->battle_status.cri/10;
- WBUFW(buf,40) = sd->status.karma;
- WBUFW(buf,42) = sd->status.manner;
+ WBUFW(buf,40) = sd->battle_status.amotion; // aspd
+ WBUFW(buf,42) = sd->status.manner; // FIXME: This is 'plusASPD', but what is it supposed to be?
WFIFOSET(fd,packet_len(0xbd));
@@ -3644,6 +3648,9 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d
if(dstsd->vender_id)
clif_showvendingboard(&dstsd->bl,dstsd->message,sd->fd);
+ if( dstsd->state.buyingstore )
+ clif_buyingstore_entry_single(sd, dstsd);
+
if(dstsd->spiritball > 0)
clif_spiritball_single(sd->fd, dstsd);
@@ -4072,6 +4079,8 @@ int clif_outsight(struct block_list *bl,va_list ap)
}
if(sd->vender_id)
clif_closevendingboard(bl,tsd->fd);
+ if( sd->state.buyingstore )
+ clif_buyingstore_disappear_entry_single(tsd, sd);
break;
case BL_ITEM:
clif_clearflooritem((struct flooritem_data*)bl,tsd->fd);
@@ -4129,42 +4138,6 @@ int clif_insight(struct block_list *bl,va_list ap)
}
/*==========================================
- *
- *------------------------------------------
-int clif_skillinfo(struct map_session_data *sd,int skillid,int type,int range)
-{
- int fd,id;
-
- nullpo_ret(sd);
-
- fd=sd->fd;
- if( (id=sd->status.skill[skillid].id) <= 0 )
- return 0;
- WFIFOHEAD(fd,packet_len(0x147));
- WFIFOW(fd,0)=0x147;
- WFIFOW(fd,2) = id;
- if(type < 0)
- WFIFOW(fd,4) = skill_get_inf(id);
- else
- WFIFOW(fd,4) = type;
- WFIFOW(fd,6) = 0;
- WFIFOW(fd,8) = sd->status.skill[skillid].lv;
- WFIFOW(fd,10) = skill_get_sp(id,sd->status.skill[skillid].lv);
- if(range < 0)
- range = skill_get_range2(&sd->bl, id,sd->status.skill[skillid].lv);
-
- WFIFOW(fd,12)= range;
- safestrncpy((char*)WFIFOP(fd,14), skill_get_name(id), NAME_LENGTH);
- if(sd->status.skill[skillid].flag ==0)
- WFIFOB(fd,38)= (sd->status.skill[skillid].lv < skill_tree_get_max(id, sd->status.class_))? 1:0;
- else
- WFIFOB(fd,38) = 0;
- WFIFOSET(fd,packet_len(0x147));
-
- return 0;
-}*/
-
-/*==========================================
* ƒXƒLƒ‹ƒŠƒXƒg‚ð‘—M‚·‚é
*------------------------------------------*/
int clif_skillinfoblock(struct map_session_data *sd)
@@ -4390,7 +4363,7 @@ int clif_skill_fail(struct map_session_data *sd,int skill_id,int type,int btype)
WFIFOW(fd,0) = 0x110;
WFIFOW(fd,2) = skill_id;
WFIFOL(fd,4) = btype;
- WFIFOB(fd,8) = 0;// success?
+ WFIFOB(fd,8) = 0;// success
WFIFOB(fd,9) = type;
WFIFOSET(fd,packet_len(0x110));
@@ -4966,6 +4939,12 @@ void clif_GlobalMessage(struct block_list* bl, const char* message)
len = strlen(message)+1;
+ if( len > sizeof(buf)-8 )
+ {
+ ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%d).\n", message, len);
+ len = sizeof(buf)-8;
+ }
+
WBUFW(buf,0)=0x8d;
WBUFW(buf,2)=len+8;
WBUFL(buf,4)=bl->id;
@@ -5057,15 +5036,8 @@ int clif_resurrection(struct block_list *bl,int type)
return 0;
}
-/// Sets the map mode.
-///
-/// mode=1 : pvp mode
-/// mode=2 : unknown mode (pk?)
-/// mode=3 : gvg mode
-/// mode=4 : message "You are in a PK area. Please beware of sudden attacks." in color 0x9B9BFF (light red)
-/// mode=5 : pvp mode
-/// mode=other : ?
-void clif_set0199(struct map_session_data* sd, int mode)
+/// Sets the map property (ZC_NOTIFY_MAPPROPERTY).
+void clif_map_property(struct map_session_data* sd, enum map_property property)
{
int fd;
@@ -5074,13 +5046,12 @@ void clif_set0199(struct map_session_data* sd, int mode)
fd=sd->fd;
WFIFOHEAD(fd,packet_len(0x199));
WFIFOW(fd,0)=0x199;
- WFIFOW(fd,2)=mode;
+ WFIFOW(fd,2)=property;
WFIFOSET(fd,packet_len(0x199));
}
-/// Set the map mode (special)
-/// 19 = battleground
-void clif_set01D6(struct map_session_data* sd, int mode)
+/// Set the map type (ZC_NOTIFY_MAPPROPERTY2)
+void clif_map_type(struct map_session_data* sd, enum map_type type)
{
int fd;
@@ -5089,7 +5060,7 @@ void clif_set01D6(struct map_session_data* sd, int mode)
fd=sd->fd;
WFIFOHEAD(fd,packet_len(0x1D6));
WFIFOW(fd,0)=0x1D6;
- WFIFOW(fd,2)=mode;
+ WFIFOW(fd,2)=type;
WFIFOSET(fd,packet_len(0x1D6));
}
@@ -5129,7 +5100,7 @@ int clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type)
/*==========================================
*
*------------------------------------------*/
-int clif_send0199(int map,int type)
+void clif_map_property_mapall(int map, enum map_property property)
{
struct block_list bl;
unsigned char buf[16];
@@ -5138,10 +5109,8 @@ int clif_send0199(int map,int type)
bl.type = BL_NUL;
bl.m = map;
WBUFW(buf,0)=0x199;
- WBUFW(buf,2)=type;
+ WBUFW(buf,2)=property;
clif_send(buf,packet_len(0x199),&bl,ALL_SAMEMAP);
-
- return 0;
}
/*==========================================
@@ -5189,7 +5158,7 @@ int clif_wis_message(int fd, const char* nick, const char* mes, int mes_len)
WFIFOW(fd,0) = 0x97;
WFIFOW(fd,2) = mes_len + NAME_LENGTH + 8;
safestrncpy((char*)WFIFOP(fd,4), nick, NAME_LENGTH);
- WFIFOL(fd,28) = 0; // unknown; if nonzero, also displays text above char
+ WFIFOL(fd,28) = 0; // isAdmin; if nonzero, also displays text above char
safestrncpy((char*)WFIFOP(fd,32), mes, mes_len);
WFIFOSET(fd,WFIFOW(fd,2));
#endif
@@ -5849,7 +5818,7 @@ int clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd)
WFIFOHEAD(fd,packet_len(0xfe));
WFIFOW(fd,0)=0xfe;
- WFIFOL(fd,2)=sd->status.account_id;
+ WFIFOL(fd,2)=sd->status.account_id; // FIXME: This is party_id
memcpy(WFIFOP(fd,6),p->party.name,NAME_LENGTH);
WFIFOSET(fd,packet_len(0xfe));
return 0;
@@ -6240,15 +6209,13 @@ int clif_sendegg(struct map_session_data *sd)
}
WFIFOHEAD(fd, MAX_INVENTORY * 2 + 4);
WFIFOW(fd,0)=0x1a6;
- if(sd->status.pet_id <= 0) {
- for(i=0,n=0;i<MAX_INVENTORY;i++){
- if(sd->status.inventory[i].nameid<=0 || sd->inventory_data[i] == NULL ||
- sd->inventory_data[i]->type!=IT_PETEGG ||
- sd->status.inventory[i].amount<=0)
- continue;
- WFIFOW(fd,n*2+4)=i+2;
- n++;
- }
+ for(i=0,n=0;i<MAX_INVENTORY;i++){
+ if(sd->status.inventory[i].nameid<=0 || sd->inventory_data[i] == NULL ||
+ sd->inventory_data[i]->type!=IT_PETEGG ||
+ sd->status.inventory[i].amount<=0)
+ continue;
+ WFIFOW(fd,n*2+4)=i+2;
+ n++;
}
WFIFOW(fd,2)=4+n*2;
WFIFOSET(fd,WFIFOW(fd,2));
@@ -7028,14 +6995,21 @@ int clif_guild_leave(struct map_session_data *sd,const char *name,const char *me
int clif_guild_expulsion(struct map_session_data *sd,const char *name,const char *mes,int account_id)
{
unsigned char buf[128];
+#if PACKETVER < 20100803
+ const unsigned short cmd = 0x15c;
+#else
+ const unsigned short cmd = 0x839;
+#endif
nullpo_ret(sd);
- WBUFW(buf, 0)=0x15c;
+ WBUFW(buf,0) = cmd;
safestrncpy((char*)WBUFP(buf, 2),name,NAME_LENGTH);
safestrncpy((char*)WBUFP(buf,26),mes,40);
+#if PACKETVER < 20100803
safestrncpy((char*)WBUFP(buf,66),"",NAME_LENGTH); // account name (not used for security reasons)
- clif_send(buf,packet_len(0x15c),&sd->bl,GUILD_NOBG);
+#endif
+ clif_send(buf,packet_len(cmd),&sd->bl,GUILD_NOBG);
return 0;
}
@@ -7561,6 +7535,12 @@ int clif_messagecolor(struct block_list* bl, unsigned long color, const char* ms
nullpo_ret(bl);
+ if( msg_len > sizeof(buf)-12 )
+ {
+ ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%u).\n", msg, msg_len);
+ msg_len = sizeof(buf)-12;
+ }
+
WBUFW(buf,0) = 0x2C1;
WBUFW(buf,2) = msg_len + 12;
WBUFL(buf,4) = bl->id;
@@ -7580,6 +7560,12 @@ int clif_message(struct block_list* bl, const char* msg)
nullpo_ret(bl);
+ if( msg_len > sizeof(buf)-8 )
+ {
+ ShowWarning("clif_message: Truncating too long message '%s' (len=%u).\n", msg, msg_len);
+ msg_len = sizeof(buf)-8;
+ }
+
WBUFW(buf,0) = 0x8d;
WBUFW(buf,2) = msg_len + 8;
WBUFL(buf,4) = bl->id;
@@ -7667,8 +7653,13 @@ int clif_charnameack (int fd, struct block_list *bl)
}
memcpy(WBUFP(buf,6), ssd->status.name, NAME_LENGTH);
- if (ssd->status.party_id > 0)
- p = party_search(ssd->status.party_id);
+ if (!battle_config.display_party_name) {
+ if (ssd->status.party_id > 0 && ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL)
+ p = party_search(ssd->status.party_id);
+ }else{
+ if (ssd->status.party_id > 0)
+ p = party_search(ssd->status.party_id);
+ }
if( ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL )
{
@@ -7783,8 +7774,13 @@ int clif_charnameupdate (struct map_session_data *ssd)
memcpy(WBUFP(buf,6), ssd->status.name, NAME_LENGTH);
- if( ssd->status.party_id > 0 )
- p = party_search(ssd->status.party_id);
+ if (!battle_config.display_party_name) {
+ if (ssd->status.party_id > 0 && ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL)
+ p = party_search(ssd->status.party_id);
+ }else{
+ if (ssd->status.party_id > 0)
+ p = party_search(ssd->status.party_id);
+ }
if( ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL )
{
@@ -8447,7 +8443,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
if( sd->state.bg_id ) clif_bg_hp(sd); // BattleGround System
if( sd->state.changemap && map[sd->bl.m].flag.battleground )
{
- clif_set01D6(sd,19); // Battleground Mode
+ clif_map_type(sd, MAPTYPE_BATTLEFIELD); // Battleground Mode
if( map[sd->bl.m].flag.battleground == 2 )
clif_bg_updatescore_single(sd);
}
@@ -8462,17 +8458,17 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
sd->pvp_won = 0;
sd->pvp_lost = 0;
}
- clif_set0199(sd,1);
+ clif_map_property(sd, MAPPROPERTY_FREEPVPZONE);
} else
// set flag, if it's a duel [LuzZza]
if(sd->duel_group)
- clif_set0199(sd,1);
+ clif_map_property(sd, MAPPROPERTY_FREEPVPZONE);
if (map[sd->bl.m].flag.gvg_dungeon)
- clif_set0199(sd,1); //TODO: Figure out the real packet to send here.
+ clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); //TODO: Figure out the real packet to send here.
if( map_flag_gvg(sd->bl.m) )
- clif_set0199(sd,3);
+ clif_map_property(sd, MAPPROPERTY_AGITZONE);
// info about nearby objects
// must use foreachinarea (CIRCULAR_AREA interferes with foreachinrange)
@@ -8876,41 +8872,6 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
map_foreachinrange(npc_chat_sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl);
#endif
- // check for special supernovice phrase
- if( (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE )
- {
- unsigned int next = pc_nextbaseexp(sd);
- if( next == 0 ) next = pc_thisbaseexp(sd);
- if( get_percentage(sd->status.base_exp, next)% 10 == 0 ) // 0%, 10%, 20%, ...
- {
- switch (sd->state.snovice_call_flag) {
- case 0:
- if( strstr(message, msg_txt(504)) ) // "Guardian Angel, can you hear my voice? ^^;"
- sd->state.snovice_call_flag++;
- break;
- case 1: {
- char buf[256];
- sprintf(buf, msg_txt(505), sd->status.name);
- if( strstr(message, buf) ) // "My name is %s, and I'm a Super Novice~"
- sd->state.snovice_call_flag++;
- }
- break;
- case 2:
- if( strstr(message, msg_txt(506)) ) // "Please help me~ T.T"
- sd->state.snovice_call_flag++;
- break;
- case 3:
- if( skillnotok(MO_EXPLOSIONSPIRITS,sd) )
- break; //Do not override the noskill mapflag. [Skotlex]
- clif_skill_nodamage(&sd->bl,&sd->bl,MO_EXPLOSIONSPIRITS,-1,
- sc_start(&sd->bl,status_skill2sc(MO_EXPLOSIONSPIRITS),100,
- 17,skill_get_time(MO_EXPLOSIONSPIRITS,1))); //Lv17-> +50 critical (noted by Poki) [Skotlex]
- sd->state.snovice_call_flag = 0;
- break;
- }
- }
- }
-
// Chat logging type 'O' / Global Chat
if( log_config.chat&1 || (log_config.chat&2 && !((agit_flag || agit2_flag) && log_config.chat&64)) )
log_chat("O", 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message);
@@ -9215,7 +9176,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
set_var(sd,output,(char *) split_data[i]);
}
- sprintf(output, "%s::OnWhisperGlobal", npc->name);
+ sprintf(output, "%s::OnWhisperGlobal", npc->exname);
npc_event(sd,output,0); // Calls the NPC label
return;
@@ -11850,30 +11811,35 @@ void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd)
}
return;
}
-/*==========================================
- * ƒXƒpƒmƒr‚Ì”š—ô”g“®
- *------------------------------------------*/
+
+
+/// Request to invoke the effect of super novice's guardian angel prayer (CZ_CHOPOKGI)
+/// 01ed
+/// Note: This packet is caused by 7 lines of any text, followed by
+/// the prayer and an another line of any text. The prayer is
+/// defined by lines 791~794 in data\msgstringtable.txt
+/// "Dear angel, can you hear my voice?"
+/// "I am" (space separated player name) "Super Novice~"
+/// "Help me out~ Please~ T_T"
void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd)
{
- if(sd){
- int nextbaseexp=pc_nextbaseexp(sd);
- if (battle_config.etc_log){
- if(nextbaseexp != 0)
- ShowInfo("SuperNovice explosionspirits!! %d %d %d %d\n",sd->bl.id,sd->status.class_,sd->status.base_exp,(int)((double)1000*sd->status.base_exp/nextbaseexp));
- else
- ShowInfo("SuperNovice explosionspirits!! %d %d %d 000\n",sd->bl.id,sd->status.class_,sd->status.base_exp);
- }
- if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_exp > 0 && nextbaseexp > 0 && (int)((double)1000*sd->status.base_exp/nextbaseexp)%100==0){
- clif_skill_nodamage(&sd->bl,&sd->bl,MO_EXPLOSIONSPIRITS,5,
- sc_start(&sd->bl,status_skill2sc(MO_EXPLOSIONSPIRITS),100,
- 5,skill_get_time(MO_EXPLOSIONSPIRITS,5)));
+ if( ( sd->class_&MAPID_UPPERMASK ) == MAPID_SUPER_NOVICE )
+ {
+ unsigned int next = pc_nextbaseexp(sd);
+
+ if( next )
+ {
+ int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. );
+
+ if( percent && ( percent%100 ) == 0 )
+ {// 10.0%, 20.0%, ..., 90.0%
+ sc_start(&sd->bl, status_skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill_get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex]
+ clif_skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions
+ }
}
}
- return;
}
-// random notes:
-// 0x214: monster/player info ?
/*==========================================
* Friends List
@@ -12383,11 +12349,69 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd)
pc_delitem(sd, item_position, 1, 0, 1);
}
-/// /check <string>
-/// S 0213 <string>.24B
+
+/// Information about character's status values (ZC_ACK_STATUS_GM)
+/// 0214 <str>.B <standardStr>.B <agi>.B <standardAgi>.B <vit>.B <standardVit>.B
+/// <int>.B <standardInt>.B <dex>.B <standardDex>.B <luk>.B <standardLuk>.B
+/// <attPower>.W <refiningPower>.W <max_mattPower>.W <min_mattPower>.W
+/// <itemdefPower>.W <plusdefPower>.W <mdefPower>.W <plusmdefPower>.W
+/// <hitSuccessValue>.W <avoidSuccessValue>.W <plusAvoidSuccessValue>.W
+/// <criticalSuccessValue>.W <ASPD>.W <plusASPD>.W
+void clif_check(int fd, struct map_session_data* pl_sd)
+{
+ WFIFOHEAD(fd,packet_len(0x214));
+ WFIFOW(fd, 0) = 0x214;
+ WFIFOB(fd, 2) = min(pl_sd->status.str, UCHAR_MAX);
+ WFIFOB(fd, 3) = pc_need_status_point(pl_sd, SP_STR);
+ WFIFOB(fd, 4) = min(pl_sd->status.agi, UCHAR_MAX);
+ WFIFOB(fd, 5) = pc_need_status_point(pl_sd, SP_AGI);
+ WFIFOB(fd, 6) = min(pl_sd->status.vit, UCHAR_MAX);
+ WFIFOB(fd, 7) = pc_need_status_point(pl_sd, SP_VIT);
+ WFIFOB(fd, 8) = min(pl_sd->status.int_, UCHAR_MAX);
+ WFIFOB(fd, 9) = pc_need_status_point(pl_sd, SP_INT);
+ WFIFOB(fd,10) = min(pl_sd->status.dex, UCHAR_MAX);
+ WFIFOB(fd,11) = pc_need_status_point(pl_sd, SP_DEX);
+ WFIFOB(fd,12) = min(pl_sd->status.luk, UCHAR_MAX);
+ WFIFOB(fd,13) = pc_need_status_point(pl_sd, SP_LUK);
+ WFIFOW(fd,14) = pl_sd->battle_status.batk+pl_sd->battle_status.rhw.atk+pl_sd->battle_status.lhw.atk;
+ WFIFOW(fd,16) = pl_sd->battle_status.rhw.atk2+pl_sd->battle_status.lhw.atk2;
+ WFIFOW(fd,18) = pl_sd->battle_status.matk_max;
+ WFIFOW(fd,20) = pl_sd->battle_status.matk_min;
+ WFIFOW(fd,22) = pl_sd->battle_status.def;
+ WFIFOW(fd,24) = pl_sd->battle_status.def2;
+ WFIFOW(fd,26) = pl_sd->battle_status.mdef;
+ WFIFOW(fd,28) = pl_sd->battle_status.mdef2;
+ WFIFOW(fd,30) = pl_sd->battle_status.hit;
+ WFIFOW(fd,32) = pl_sd->battle_status.flee;
+ WFIFOW(fd,34) = pl_sd->battle_status.flee2/10;
+ WFIFOW(fd,36) = pl_sd->battle_status.cri/10;
+ WFIFOW(fd,38) = (2000-pl_sd->battle_status.amotion)/10; // aspd
+ WFIFOW(fd,40) = 0; // FIXME: What is 'plusASPD' supposed to be?
+ WFIFOSET(fd,packet_len(0x214));
+}
+
+
+/// Request character's status values (CZ_REQ_STATUS_GM)
+/// /check <char name>
+/// 0213 <char name>.24B
void clif_parse_Check(int fd, struct map_session_data *sd)
{
- // no info
+ char charname[NAME_LENGTH];
+ struct map_session_data* pl_sd;
+
+ if( pc_isGM(sd) < battle_config.gm_check_minlevel )
+ {
+ return;
+ }
+
+ safestrncpy(charname, (const char*)RFIFOP(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), sizeof(charname));
+
+ if( ( pl_sd = map_nick2sd(charname) ) == NULL || pc_isGM(sd) < pc_isGM(pl_sd) )
+ {
+ return;
+ }
+
+ clif_check(fd, pl_sd);
}
#ifndef TXT_ONLY
@@ -12826,7 +12850,7 @@ void clif_Auction_openwindow(struct map_session_data *sd)
{
int fd = sd->fd;
- if( sd->state.storage_flag || sd->vender_id || sd->state.trading )
+ if( sd->state.storage_flag || sd->vender_id || sd->state.buyingstore || sd->state.trading )
return;
WFIFOHEAD(fd,12);
@@ -13244,8 +13268,13 @@ void clif_parse_Adopt_reply(int fd, struct map_session_data *sd)
}
/*==========================================
- * Convex Mirror
- * S 0293 <flag>.b <x>.l <y>.l <Hours>.w <Minutes>.w <unknown>.l <monster name>.40B <unknown>.11B
+ * Convex Mirror (ZC_BOSS_INFO)
+ * S 0293 <infoType>.B <x>.L <y>.L <minHours>.W <minMinutes>.W <maxHours>.W <maxMinutes>.W <monster name>.51B
+ * infoType:
+ * 0 = No boss on this map (BOSS_INFO_NOT).
+ * 1 = Boss is alive (position update) (BOSS_INFO_ALIVE).
+ * 2 = Boss is alive (initial announce) (BOSS_INFO_ALIVE_WITHMSG).
+ * 3 = Boss is dead (BOSS_INFO_DEAD).
*==========================================*/
void clif_bossmapinfo(int fd, struct mob_data *md, short flag)
{
@@ -14003,23 +14032,529 @@ void clif_showdigit(struct map_session_data* sd, unsigned char type, int value)
WFIFOSET(sd->fd, packet_len(0x1b1));
}
-/*==========================================
- * ƒpƒPƒbƒgƒfƒoƒbƒO
- *------------------------------------------*/
+
+/// Buying Store System
+///
+
+/// Opens preparation window for buying store (ZC_OPEN_BUYING_STORE)
+/// 0810 <slots>.B
+void clif_buyingstore_open(struct map_session_data* sd)
+{
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd,packet_len(0x810));
+ WFIFOW(fd,0) = 0x810;
+ WFIFOB(fd,2) = sd->buyingstore.slots;
+ WFIFOSET(fd,packet_len(0x810));
+}
+
+
+/// Request to create a buying store (CZ_REQ_OPEN_BUYING_STORE)
+/// 0811 <packet len>.W <limit zeny>.L <result>.B <store name>.80B { <name id>.W <amount>.W <price>.L }*
+/// result:
+/// 0 = cancel
+/// 1 = open
+static void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd)
+{
+ const unsigned int blocksize = 8;
+ uint8* itemlist;
+ char storename[MESSAGE_SIZE];
+ unsigned char result;
+ int zenylimit;
+ unsigned int count, packet_len;
+ struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)];
+
+ packet_len = RFIFOW(fd,info->pos[0]);
+
+ // TODO: Make this check global for all variable length packets.
+ if( packet_len < 89 )
+ {// minimum packet length
+ ShowError("clif_parse_ReqOpenBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 89, packet_len, sd->bl.id);
+ return;
+ }
+
+ zenylimit = RFIFOL(fd,info->pos[1]);
+ result = RFIFOL(fd,info->pos[2]);
+ safestrncpy(storename, (const char*)RFIFOP(fd,info->pos[3]), sizeof(storename));
+ itemlist = RFIFOP(fd,info->pos[4]);
+
+ // so that buyingstore_create knows, how many elements it has access to
+ packet_len-= info->pos[4];
+
+ if( packet_len%blocksize )
+ {
+ ShowError("clif_parse_ReqOpenBuyingStore: Unexpected item list size %u (account_id=%d, block size=%u)\n", packet_len, sd->bl.id, blocksize);
+ return;
+ }
+ count = packet_len/blocksize;
+
+ buyingstore_create(sd, zenylimit, result, storename, itemlist, count);
+}
+
+
+/// Notification, that the requested buying store could not be created (ZC_FAILED_OPEN_BUYING_STORE_TO_BUYER)
+/// 0812 <result>.W <total weight>.L
+/// result:
+/// 1 = "Failed to open buying store." (0x6cd, MSI_BUYINGSTORE_OPEN_FAILED)
+/// 2 = "Total amount of then possessed items exceeds the weight limit by <weight/10-maxweight*90%>. Please re-enter." (0x6ce, MSI_BUYINGSTORE_OVERWEIGHT)
+/// 8 = "No sale (purchase) information available." (0x705)
+/// other = nothing
+void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short result, unsigned int weight)
+{
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd,packet_len(0x812));
+ WFIFOW(fd,0) = 0x812;
+ WFIFOW(fd,2) = result;
+ WFIFOL(fd,4) = weight;
+ WFIFOSET(fd,packet_len(0x812));
+}
+
+
+/// Notification, that the requested buying store was created (ZC_MYITEMLIST_BUYING_STORE)
+/// 0813 <packet len>.W <account id>.L <limit zeny>.L { <price>.L <count>.W <type>.B <name id>.W }*
+void clif_buyingstore_myitemlist(struct map_session_data* sd)
+{
+ int fd = sd->fd;
+ unsigned int i;
+
+ WFIFOHEAD(fd,12+sd->buyingstore.slots*9);
+ WFIFOW(fd,0) = 0x813;
+ WFIFOW(fd,2) = 12+sd->buyingstore.slots*9;
+ WFIFOL(fd,4) = sd->bl.id;
+ WFIFOL(fd,8) = sd->buyingstore.zenylimit;
+
+ for( i = 0; i < sd->buyingstore.slots; i++ )
+ {
+ WFIFOL(fd,12+i*9) = sd->buyingstore.items[i].price;
+ WFIFOW(fd,16+i*9) = sd->buyingstore.items[i].amount;
+ WFIFOB(fd,18+i*9) = itemtype(itemdb_type(sd->buyingstore.items[i].nameid));
+ WFIFOW(fd,19+i*9) = sd->buyingstore.items[i].nameid;
+ }
+
+ WFIFOSET(fd,WFIFOW(fd,2));
+}
+
+
+/// Notifies clients in area of a buying store (ZC_BUYING_STORE_ENTRY)
+/// 0814 <account id>.L <store name>.80B
+void clif_buyingstore_entry(struct map_session_data* sd)
+{
+ uint8 buf[86];
+
+ WBUFW(buf,0) = 0x814;
+ WBUFL(buf,2) = sd->bl.id;
+ memcpy(WBUFP(buf,6), sd->message, MESSAGE_SIZE);
+
+ clif_send(buf, packet_len(0x814), &sd->bl, AREA_WOS);
+}
+void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd)
+{
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd,packet_len(0x814));
+ WFIFOW(fd,0) = 0x814;
+ WFIFOL(fd,2) = pl_sd->bl.id;
+ memcpy(WFIFOP(fd,6), pl_sd->message, MESSAGE_SIZE);
+ WFIFOSET(fd,packet_len(0x814));
+}
+
+
+/// Request to close own buying store (CZ_REQ_CLOSE_BUYING_STORE)
+/// 0815
+static void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data* sd)
+{
+ buyingstore_close(sd);
+}
+
+
+/// Notifies clients in area that a buying store was closed (ZC_DISAPPEAR_BUYING_STORE_ENTRY)
+/// 0816 <account id>.L
+void clif_buyingstore_disappear_entry(struct map_session_data* sd)
+{
+ uint8 buf[6];
+
+ WBUFW(buf,0) = 0x816;
+ WBUFL(buf,2) = sd->bl.id;
+
+ clif_send(buf, packet_len(0x816), &sd->bl, AREA_WOS);
+}
+void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd)
+{
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd,packet_len(0x816));
+ WFIFOW(fd,0) = 0x816;
+ WFIFOL(fd,2) = pl_sd->bl.id;
+ WFIFOSET(fd,packet_len(0x816));
+}
+
+
+/// Request to open someone else's buying store (CZ_REQ_CLICK_TO_BUYING_STORE)
+/// 0817 <account id>.L
+static void clif_parse_ReqClickBuyingStore(int fd, struct map_session_data* sd)
+{
+ int account_id;
+
+ account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]);
+
+ buyingstore_open(sd, account_id);
+}
+
+
+/// Sends buying store item list (ZC_ACK_ITEMLIST_BUYING_STORE)
+/// 0818 <packet len>.W <account id>.L <store id>.L <limit zeny>.L { <price>.L <amount>.W <type>.B <name id>.W }*
+void clif_buyingstore_itemlist(struct map_session_data* sd, struct map_session_data* pl_sd)
+{
+ int fd = sd->fd;
+ unsigned int i;
+
+ WFIFOHEAD(fd,16+pl_sd->buyingstore.slots*9);
+ WFIFOW(fd,0) = 0x818;
+ WFIFOW(fd,2) = 16+pl_sd->buyingstore.slots*9;
+ WFIFOL(fd,4) = pl_sd->bl.id;
+ WFIFOL(fd,8) = pl_sd->buyer_id;
+ WFIFOL(fd,12) = pl_sd->buyingstore.zenylimit;
+
+ for( i = 0; i < pl_sd->buyingstore.slots; i++ )
+ {
+ WFIFOL(fd,16+i*9) = pl_sd->buyingstore.items[i].price;
+ WFIFOW(fd,20+i*9) = pl_sd->buyingstore.items[i].amount; // TODO: Figure out, if no longer needed items (amount == 0) are listed on official.
+ WFIFOB(fd,22+i*9) = itemtype(itemdb_type(pl_sd->buyingstore.items[i].nameid));
+ WFIFOW(fd,23+i*9) = pl_sd->buyingstore.items[i].nameid;
+ }
+
+ WFIFOSET(fd,WFIFOW(fd,2));
+}
+
+
+/// Request to sell items to a buying store (CZ_REQ_TRADE_BUYING_STORE)
+/// 0819 <packet len>.W <account id>.L <store id>.L { <index>.W <name id>.W <amount>.W }*
+static void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd)
+{
+ const unsigned int blocksize = 6;
+ uint8* itemlist;
+ int account_id;
+ unsigned int count, packet_len, buyer_id;
+ struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)];
+
+ packet_len = RFIFOW(fd,info->pos[0]);
+
+ if( packet_len < 12 )
+ {// minimum packet length
+ ShowError("clif_parse_ReqTradeBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 12, packet_len, sd->bl.id);
+ return;
+ }
+
+ account_id = RFIFOL(fd,info->pos[1]);
+ buyer_id = RFIFOL(fd,info->pos[2]);
+ itemlist = RFIFOP(fd,info->pos[3]);
+
+ // so that buyingstore_trade knows, how many elements it has access to
+ packet_len-= info->pos[3];
+
+ if( packet_len%blocksize )
+ {
+ ShowError("clif_parse_ReqTradeBuyingStore: Unexpected item list size %u (account_id=%d, buyer_id=%d, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize);
+ return;
+ }
+ count = packet_len/blocksize;
+
+ buyingstore_trade(sd, account_id, buyer_id, itemlist, count);
+}
+
+
+/// Notifies the buyer, that the buying store has been closed due to a post-trade condition (ZC_FAILED_TRADE_BUYING_STORE_TO_BUYER)
+/// 081a <result>.W
+/// result:
+/// 3 = "All items within the buy limit were purchased." (0x6cf, MSI_BUYINGSTORE_TRADE_OVERLIMITZENY)
+/// 4 = "All items were purchased." (0x6d0, MSI_BUYINGSTORE_TRADE_BUYCOMPLETE)
+/// other = nothing
+void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short result)
+{
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd,packet_len(0x81a));
+ WFIFOW(fd,0) = 0x81a;
+ WFIFOW(fd,2) = result;
+ WFIFOSET(fd,packet_len(0x81a));
+}
+
+
+/// Updates the zeny limit and an item in the buying store item list (ZC_UPDATE_ITEM_FROM_BUYING_STORE)
+/// 081b <name id>.W <amount>.W <limit zeny>.L
+void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short nameid, unsigned short amount)
+{
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd,packet_len(0x81b));
+ WFIFOW(fd,0) = 0x81b;
+ WFIFOW(fd,2) = nameid;
+ WFIFOW(fd,4) = amount; // amount of nameid received
+ WFIFOW(fd,6) = sd->buyingstore.zenylimit;
+ WFIFOSET(fd,packet_len(0x81b));
+}
+
+
+/// Deletes item from inventory, that was sold to a buying store (ZC_ITEM_DELETE_BUYING_STORE)
+/// 081c <index>.W <amount>.W <price>.L
+/// message:
+/// "%s (%d) were sold at %dz." (0x6d2, MSI_BUYINGSTORE_TRADE_SELLCOMPLETE)
+///
+/// @note This function has to be called _instead_ of clif_delitem/clif_dropitem.
+void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsigned short amount, int price)
+{
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd,packet_len(0x81c));
+ WFIFOW(fd,0) = 0x81c;
+ WFIFOW(fd,2) = index+2;
+ WFIFOW(fd,4) = amount;
+ WFIFOL(fd,6) = price; // price per item, client calculates total Zeny by itself
+ WFIFOSET(fd,packet_len(0x81c));
+}
+
+
+/// Notifies the seller, that a buying store trade failed (ZC_FAILED_TRADE_BUYING_STORE_TO_SELLER)
+/// 0824 <result>.W <name id>.W
+/// result:
+/// 5 = "The deal has failed." (0x39, MSI_DEAL_FAIL)
+/// 6 = "The trade failed, because the entered amount of item %s is higher, than the buyer is willing to buy." (0x6d3, MSI_BUYINGSTORE_TRADE_OVERCOUNT)
+/// 7 = "The trade failed, because the buyer is lacking required balance." (0x6d1, MSI_BUYINGSTORE_TRADE_LACKBUYERZENY)
+/// other = nothing
+void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short result, unsigned short nameid)
+{
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd,packet_len(0x824));
+ WFIFOW(fd,0) = 0x824;
+ WFIFOW(fd,2) = result;
+ WFIFOW(fd,4) = nameid;
+ WFIFOSET(fd,packet_len(0x824));
+}
+
+
+/// Search Store Info System
+///
+
+/// Request to search for stores (CZ_SEARCH_STORE_INFO)
+/// 0835 <packet len>.W <type>.B <max price>.L <min price>.L <name id count>.B <card count>.B { <name id>.W }* { <card>.W }*
+/// type:
+/// 0 = Vending
+/// 1 = Buying Store
+///
+/// @note The client determines the item ids by specifying a name and optionally,
+/// amount of card slots. If the client does not know about the item it
+/// cannot be searched.
+static void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd)
+{
+ const unsigned int blocksize = 2;
+ const uint8* itemlist;
+ const uint8* cardlist;
+ unsigned char type;
+ unsigned int min_price, max_price, packet_len, count, item_count, card_count;
+ struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)];
+
+ packet_len = RFIFOW(fd,info->pos[0]);
+
+ if( packet_len < 15 )
+ {// minimum packet length
+ ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 15, packet_len, sd->bl.id);
+ return;
+ }
+
+ type = RFIFOB(fd,info->pos[1]);
+ max_price = RFIFOL(fd,info->pos[2]);
+ min_price = RFIFOL(fd,info->pos[3]);
+ item_count = RFIFOB(fd,info->pos[4]);
+ card_count = RFIFOB(fd,info->pos[5]);
+ itemlist = RFIFOP(fd,info->pos[6]);
+ cardlist = RFIFOP(fd,info->pos[6]+blocksize*item_count);
+
+ // check, if there is enough data for the claimed count of items
+ packet_len-= info->pos[6];
+
+ if( packet_len%blocksize )
+ {
+ ShowError("clif_parse_SearchStoreInfo: Unexpected item list size %u (account_id=%d, block size=%u)\n", packet_len, sd->bl.id, blocksize);
+ return;
+ }
+ count = packet_len/blocksize;
+
+ if( count < item_count+card_count )
+ {
+ ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected count=%u, count=%u, account_id=%d).\n", item_count+card_count, count, sd->bl.id);
+ return;
+ }
+
+ searchstore_query(sd, type, min_price, max_price, (const unsigned short*)itemlist, item_count, (const unsigned short*)cardlist, card_count);
+}
+
+
+/// Results for a store search request (ZC_SEARCH_STORE_INFO_ACK)
+/// 0836 <packet len>.W <is first page>.B <is next page>.B <remaining uses>.B { <store id>.L <account id>.L <shop name>.80B <nameid>.W <item type>.B <price>.L <amount>.W <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }*
+/// is first page:
+/// 0 = appends to existing results
+/// 1 = clears previous results before displaying this result set
+/// is next page:
+/// 0 = no "next" label
+/// 1 = "next" label to retrieve more results
+void clif_search_store_info_ack(struct map_session_data* sd)
+{
+ const unsigned int blocksize = MESSAGE_SIZE+26;
+ int fd = sd->fd;
+ unsigned int i, start, end;
+
+ start = sd->searchstore.pages*SEARCHSTORE_RESULTS_PER_PAGE;
+ end = min(sd->searchstore.count, start+SEARCHSTORE_RESULTS_PER_PAGE);
+
+ WFIFOHEAD(fd,7+(end-start)*blocksize);
+ WFIFOW(fd,0) = 0x836;
+ WFIFOW(fd,2) = 7+(end-start)*blocksize;
+ WFIFOB(fd,4) = !sd->searchstore.pages;
+ WFIFOB(fd,5) = searchstore_querynext(sd);
+ WFIFOB(fd,6) = (unsigned char)min(sd->searchstore.uses, UCHAR_MAX);
+
+ for( i = start; i < end; i++ )
+ {
+ struct s_search_store_info_item* ssitem = &sd->searchstore.items[i];
+ struct item it;
+
+ WFIFOL(fd,i*blocksize+ 7) = ssitem->store_id;
+ WFIFOL(fd,i*blocksize+11) = ssitem->account_id;
+ memcpy(WFIFOP(fd,i*blocksize+15), ssitem->store_name, MESSAGE_SIZE);
+ WFIFOW(fd,i*blocksize+15+MESSAGE_SIZE) = ssitem->nameid;
+ WFIFOB(fd,i*blocksize+17+MESSAGE_SIZE) = itemtype(itemdb_type(ssitem->nameid));
+ WFIFOL(fd,i*blocksize+18+MESSAGE_SIZE) = ssitem->price;
+ WFIFOW(fd,i*blocksize+22+MESSAGE_SIZE) = ssitem->amount;
+ WFIFOB(fd,i*blocksize+24+MESSAGE_SIZE) = ssitem->refine;
+
+ // make-up an item for clif_addcards
+ memset(&it, 0, sizeof(it));
+ memcpy(&it.card, &ssitem->card, sizeof(it.card));
+ it.nameid = ssitem->nameid;
+ it.amount = ssitem->amount;
+
+ clif_addcards(WFIFOP(fd,i*blocksize+25+MESSAGE_SIZE), &it);
+ }
+
+ WFIFOSET(fd,WFIFOW(fd,2));
+}
+
+
+/// Notification of failure when searching for stores (ZC_SEARCH_STORE_INFO_FAILED)
+/// 0837 <reason>.B
+/// reason:
+/// 0 = "No matching stores were found." (0x70b)
+/// 1 = "There are too many results. Please enter more detailed search term." (0x6f8)
+/// 2 = "You cannot search anymore." (0x706)
+/// 3 = "You cannot search yet." (0x708)
+/// 4 = "No sale (purchase) information available." (0x705)
+void clif_search_store_info_failed(struct map_session_data* sd, unsigned char reason)
+{
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd,packet_len(0x837));
+ WFIFOW(fd,0) = 0x837;
+ WFIFOB(fd,2) = reason;
+ WFIFOSET(fd,packet_len(0x837));
+}
+
+
+/// Request to display next page of results (CZ_SEARCH_STORE_INFO_NEXT_PAGE)
+/// 0838
+static void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd)
+{
+ searchstore_next(sd);
+}
+
+
+/// Opens the search store window (ZC_OPEN_SEARCH_STORE_INFO)
+/// 083a <type>.W <remaining uses>.B
+/// type:
+/// 0 = Search Stores
+/// 1 = Search Stores (Cash), asks for confirmation, when clicking a store
+void clif_open_search_store_info(struct map_session_data* sd)
+{
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd,packet_len(0x83a));
+ WFIFOW(fd,0) = 0x83a;
+ WFIFOW(fd,2) = sd->searchstore.effect;
+#if PACKETVER > 20100701
+ WFIFOB(fd,4) = (unsigned char)min(sd->searchstore.uses, UCHAR_MAX);
+#endif
+ WFIFOSET(fd,packet_len(0x83a));
+}
+
+
+/// Request to close the store search window (CZ_CLOSE_SEARCH_STORE_INFO)
+/// 083b
+static void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data* sd)
+{
+ searchstore_close(sd);
+}
+
+
+/// Request to invoke catalog effect on a store from search results (CZ_SSILIST_ITEM_CLICK)
+/// 083c <account id>.L <store id>.L <nameid>.W
+static void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data* sd)
+{
+ unsigned short nameid;
+ int account_id, store_id;
+ struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)];
+
+ account_id = RFIFOL(fd,info->pos[0]);
+ store_id = RFIFOL(fd,info->pos[1]);
+ nameid = RFIFOW(fd,info->pos[2]);
+
+ searchstore_click(sd, account_id, store_id, nameid);
+}
+
+
+/// Notification of the store position on current map (ZC_SSILIST_ITEM_CLICK_ACK)
+/// 083d <xPos>.W <yPos>.W
+void clif_search_store_info_click_ack(struct map_session_data* sd, short x, short y)
+{
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd,packet_len(0x83d));
+ WFIFOW(fd,0) = 0x83d;
+ WFIFOW(fd,2) = x;
+ WFIFOW(fd,4) = y;
+ WFIFOSET(fd,packet_len(0x83d));
+}
+
+
+/// Parse function for packet debugging
void clif_parse_debug(int fd,struct map_session_data *sd)
{
- int i, cmd, len;
+ int cmd, packet_len;
+ // clif_parse ensures, that there is at least 2 bytes of data
cmd = RFIFOW(fd,0);
- len = sd?packet_db[sd->packet_ver][cmd].len:RFIFOREST(fd); //With no session, just read the remaining in the buffer.
- ShowDebug("packet debug 0x%4X\n",cmd);
- ShowMessage("---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F");
- for(i=0;i<len;i++){
- if((i&15)==0)
- ShowMessage("\n%04X ",i);
- ShowMessage("%02X ",RFIFOB(fd,i));
+
+ if( sd )
+ {
+ packet_len = packet_db[sd->packet_ver][cmd].len;
+
+ if( packet_len == 0 )
+ {// unknown
+ packet_len = RFIFOREST(fd);
+ }
+ else if( packet_len == -1 )
+ {// variable length
+ packet_len = RFIFOW(fd,2); // clif_parse ensures, that this amount of data is already received
+ }
+ ShowDebug("Packet debug of 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id);
+ }
+ else
+ {
+ packet_len = RFIFOREST(fd);
+ ShowDebug("Packet debug of 0x%04X (length %d), session #%d\n", cmd, packet_len, fd);
}
- ShowMessage("\n");
+
+ ShowDump(RFIFOP(fd,0), packet_len);
}
/*==========================================
@@ -14089,6 +14624,9 @@ int clif_parse(int fd)
WFIFOW(fd,0) = 0x6a;
WFIFOB(fd,2) = 3; // Rejected from Server
WFIFOSET(fd,packet_len(0x6a));
+#ifdef DUMP_INVALID_PACKET
+ ShowDump(RFIFOP(fd,0), RFIFOREST(fd));
+#endif
RFIFOSKIP(fd, RFIFOREST(fd));
set_eof(fd);
return 0;
@@ -14098,6 +14636,9 @@ int clif_parse(int fd)
// filter out invalid / unsupported packets
if (cmd > MAX_PACKET_DB || packet_db[packet_ver][cmd].len == 0) {
ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x, %d bytes received), disconnecting session #%d.\n", cmd, RFIFOREST(fd), fd);
+#ifdef DUMP_INVALID_PACKET
+ ShowDump(RFIFOP(fd,0), RFIFOREST(fd));
+#endif
set_eof(fd);
return 0;
}
@@ -14111,6 +14652,9 @@ int clif_parse(int fd)
packet_len = RFIFOW(fd,2);
if (packet_len < 4 || packet_len > 32768) {
ShowWarning("clif_parse: Received packet 0x%04x specifies invalid packet_len (%d), disconnecting session #%d.\n", cmd, packet_len, fd);
+#ifdef DUMP_INVALID_PACKET
+ ShowDump(RFIFOP(fd,0), RFIFOREST(fd));
+#endif
set_eof(fd);
return 0;
}
@@ -14134,58 +14678,45 @@ int clif_parse(int fd)
else
packet_db[packet_ver][cmd].func(fd, sd);
}
-#if DUMP_UNKNOWN_PACKET
- else if (battle_config.error_log)
+#ifdef DUMP_UNKNOWN_PACKET
+ else
{
- int i;
- FILE *fp;
- char packet_txt[256] = "save/packet.txt";
- time_t now;
- dump = 1;
+ const char* packet_txt = "save/packet.txt";
+ FILE* fp;
- if ((fp = fopen(packet_txt, "a")) == NULL) {
- ShowError("clif.c: can't write [%s] !!! data is lost !!!\n", packet_txt);
- return 1;
- } else {
- time(&now);
- if (sd && sd->state.active) {
- fprintf(fp, "%sPlayer with account ID %d (character ID %d, player name %s) sent wrong packet:\n",
- asctime(localtime(&now)), sd->status.account_id, sd->status.char_id, sd->status.name);
- } else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified)
- fprintf(fp, "%sPlayer with account ID %d sent wrong packet:\n", asctime(localtime(&now)), sd->bl.id);
-
- fprintf(fp, "\t---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F");
- for(i = 0; i < packet_len; i++) {
- if ((i & 15) == 0)
- fprintf(fp, "\n\t%04X ", i);
- fprintf(fp, "%02X ", RFIFOB(fd,i));
+ if((fp = fopen(packet_txt, "a"))!=NULL)
+ {
+ if( sd )
+ {
+ fprintf(fp, "Unknown packet 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id);
}
- fprintf(fp, "\n\n");
+ else
+ {
+ fprintf(fp, "Unknown packet 0x%04X (length %d), session #%d\n", cmd, packet_len, fd);
+ }
+
+ WriteDump(fp, RFIFOP(fd,0), packet_len);
+ fprintf(fp, "\n");
fclose(fp);
}
- }
-#endif
+ else
+ {
+ ShowError("Failed to write '%s'.\n", packet_txt);
- /* TODO: use utils.c :: dump()
- if (dump) {
- int i;
- ShowDebug("\nclif_parse: session #%d, packet 0x%04x, length %d, version %d\n", fd, cmd, packet_len, packet_ver);
- ShowMessage("---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F");
- for(i = 0; i < packet_len; i++) {
- if ((i & 15) == 0)
- ShowMessage("\n%04X ",i);
- ShowMessage("%02X ", RFIFOB(fd,i));
- }
- ShowMessage("\n");
- if (sd && sd->state.active) {
- if (sd->status.name != NULL)
- ShowMessage("\nAccount ID %d, character ID %d, player name %s.\n",
- sd->status.account_id, sd->status.char_id, sd->status.name);
+ // Dump on console instead
+ if( sd )
+ {
+ ShowDebug("Unknown packet 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id);
+ }
else
- ShowMessage("\nAccount ID %d.\n", sd->bl.id);
- } else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified)
- ShowMessage("\nAccount ID %d.\n", sd->bl.id);
- }*/
+ {
+ ShowDebug("Unknown packet 0x%04X (length %d), session #%d\n", cmd, packet_len, fd);
+ }
+
+ ShowDump(RFIFOP(fd,0), packet_len);
+ }
+ }
+#endif
RFIFOSKIP(fd, packet_len);
@@ -14405,9 +14936,9 @@ static int packetdb_readdb(void)
#else // for Party booking ( PACKETVER >= 20091229 )
-1, -1, 18, 4, 8, 6, 2, 4, 14, 50, 18, 6, 2, 3, 14, 20,
#endif
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, -1, 8, -1, 86, 2, 6, 6, -1, -1, 4, 10, 10, 0, 0, 0,
+ 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, -1, -1, 3, 2, 66, 5, 2, 12, 6, 0, 0,
};
struct {
void (*func)(int, struct map_session_data *);
@@ -14598,6 +15129,16 @@ static int packetdb_readdb(void)
{clif_parse_PartyBookingDeleteReq,"bookingdelreq"},
#endif
{clif_parse_PVPInfo,"pvpinfo"},
+ // Buying Store
+ {clif_parse_ReqOpenBuyingStore,"reqopenbuyingstore"},
+ {clif_parse_ReqCloseBuyingStore,"reqclosebuyingstore"},
+ {clif_parse_ReqClickBuyingStore,"reqclickbuyingstore"},
+ {clif_parse_ReqTradeBuyingStore,"reqtradebuyingstore"},
+ // Store Search
+ {clif_parse_SearchStoreInfo,"searchstoreinfo"},
+ {clif_parse_SearchStoreInfoNextPage,"searchstoreinfonextpage"},
+ {clif_parse_CloseSearchStoreInfo,"closesearchstoreinfo"},
+ {clif_parse_SearchStoreInfoListItemClick,"searchstoreinfolistitemclick"},
{NULL,NULL}
};
diff --git a/src/map/clif.h b/src/map/clif.h
index 8e9f2be7a..85293405d 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -173,6 +173,43 @@ typedef enum clr_type
CLR_TELEPORT,
} clr_type;
+enum map_property
+{// clif_map_property
+ MAPPROPERTY_NOTHING = 0,
+ MAPPROPERTY_FREEPVPZONE = 1,
+ MAPPROPERTY_EVENTPVPZONE = 2,
+ MAPPROPERTY_AGITZONE = 3,
+ MAPPROPERTY_PKSERVERZONE = 4, // message "You are in a PK area. Please beware of sudden attacks." in color 0x9B9BFF (light red)
+ MAPPROPERTY_PVPSERVERZONE = 5,
+ MAPPROPERTY_DENYSKILLZONE = 6,
+};
+
+enum map_type
+{// clif_map_type
+ MAPTYPE_VILLAGE = 0,
+ MAPTYPE_VILLAGE_IN = 1,
+ MAPTYPE_FIELD = 2,
+ MAPTYPE_DUNGEON = 3,
+ MAPTYPE_ARENA = 4,
+ MAPTYPE_PENALTY_FREEPKZONE = 5,
+ MAPTYPE_NOPENALTY_FREEPKZONE = 6,
+ MAPTYPE_EVENT_GUILDWAR = 7,
+ MAPTYPE_AGIT = 8,
+ MAPTYPE_DUNGEON2 = 9,
+ MAPTYPE_DUNGEON3 = 10,
+ MAPTYPE_PKSERVER = 11,
+ MAPTYPE_PVPSERVER = 12,
+ MAPTYPE_DENYSKILL = 13,
+ MAPTYPE_TURBOTRACK = 14,
+ MAPTYPE_JAIL = 15,
+ MAPTYPE_MONSTERTRACK = 16,
+ MAPTYPE_PORINGBATTLE = 17,
+ MAPTYPE_AGIT_SIEGEV15 = 18,
+ MAPTYPE_BATTLEFIELD = 19,
+ MAPTYPE_PVP_TOURNAMENT = 20,
+ MAPTYPE_UNUSED = 29,
+};
+
int clif_setip(const char* ip);
void clif_setbindip(const char* ip);
void clif_setport(uint16 port);
@@ -284,7 +321,6 @@ int clif_class_change(struct block_list *bl,int class_,int type);
#define clif_mob_class_change(md, class_) clif_class_change(&md->bl, class_, 1)
int clif_mob_equip(struct mob_data *md,int nameid); // [Valaris]
-int clif_skillinfo(struct map_session_data *sd,int skillid,int type,int range);
int clif_skillinfoblock(struct map_session_data *sd);
int clif_skillup(struct map_session_data *sd,int skill_num);
int clif_addskill(struct map_session_data *sd, int skill);
@@ -438,9 +474,9 @@ void clif_MainChatMessage(const char* message); //luzza
int clif_broadcast2(struct block_list *bl, const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target);
int clif_heal(int fd,int type,int val);
int clif_resurrection(struct block_list *bl,int type);
-void clif_set0199(struct map_session_data* sd, int mode);
+void clif_map_property(struct map_session_data* sd, enum map_property property);
int clif_pvpset(struct map_session_data *sd, int pvprank, int pvpnum,int type);
-int clif_send0199(int map,int type);
+void clif_map_property_mapall(int map, enum map_property property);
void clif_refine(int fd, int fail, int index, int val);
void clif_upgrademessage(int fd, int result, int item_id);
@@ -569,4 +605,24 @@ void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_boo
void clif_showdigit(struct map_session_data* sd, unsigned char type, int value);
+/// Buying Store System
+void clif_buyingstore_open(struct map_session_data* sd);
+void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short result, unsigned int weight);
+void clif_buyingstore_myitemlist(struct map_session_data* sd);
+void clif_buyingstore_entry(struct map_session_data* sd);
+void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd);
+void clif_buyingstore_disappear_entry(struct map_session_data* sd);
+void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd);
+void clif_buyingstore_itemlist(struct map_session_data* sd, struct map_session_data* pl_sd);
+void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short result);
+void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short nameid, unsigned short amount);
+void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsigned short amount, int price);
+void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short result, unsigned short nameid);
+
+/// Search Store System
+void clif_search_store_info_ack(struct map_session_data* sd);
+void clif_search_store_info_failed(struct map_session_data* sd, unsigned char reason);
+void clif_open_search_store_info(struct map_session_data* sd);
+void clif_search_store_info_click_ack(struct map_session_data* sd, short x, short y);
+
#endif /* _CLIF_H_ */
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index bf801fefd..92fe757c8 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -703,6 +703,32 @@ static bool itemdb_read_stack(char* fields[], int columns, int current)
return true;
}
+/// Reads items allowed to be sold in buying stores
+static bool itemdb_read_buyingstore(char* fields[], int columns, int current)
+{// <nameid>
+ int nameid;
+ struct item_data* id;
+
+ nameid = atoi(fields[0]);
+
+ if( ( id = itemdb_exists(nameid) ) == NULL )
+ {
+ ShowWarning("itemdb_read_buyingstore: Invalid item id %d.\n", nameid);
+ return false;
+ }
+
+ if( !itemdb_isstackable2(id) )
+ {
+ ShowWarning("itemdb_read_buyingstore: Non-stackable item id %d cannot be enabled for buying store.\n", nameid);
+ return false;
+ }
+
+ id->flag.buyingstore = true;
+
+ return true;
+}
+
+
/*======================================
* Applies gender restrictions according to settings. [Skotlex]
*======================================*/
@@ -1019,6 +1045,7 @@ static void itemdb_read(void)
sv_readdb(db_path, "item_noequip.txt", ',', 2, 2, -1, &itemdb_read_noequip);
sv_readdb(db_path, "item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade);
sv_readdb(db_path, "item_delay.txt", ',', 2, 2, MAX_ITEMDELAYS, &itemdb_read_itemdelay);
+ sv_readdb(db_path, "item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore);
sv_readdb(db_path, "item_stack.txt", ',', 3, 3, -1, &itemdb_read_stack);
}
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index 1b8917277..b24944fb5 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -76,6 +76,7 @@ struct item_data {
unsigned delay_consume : 1; // Signifies items that are not consumed immediately upon double-click [Skotlex]
unsigned trade_restriction : 7; //Item restrictions mask [Skotlex]
unsigned autoequip: 1;
+ unsigned buyingstore : 1;
} flag;
struct
{// item stacking limitation
diff --git a/src/map/log.c b/src/map/log.c
index bf6133684..72cfe46d3 100644
--- a/src/map/log.c
+++ b/src/map/log.c
@@ -492,31 +492,31 @@ int log_config_read(char *cfgName)
else if(strcmpi(w1, "log_branch_file") == 0) {
strcpy(log_config.log_branch, w2);
if(log_config.branch > 0 && !log_config.sql_logs)
- ShowNotice("Logging Dead Branch Usage to file `%s`.txt\n", w2);
+ ShowNotice("Logging Dead Branch Usage to file `%s`\n", w2);
} else if(strcmpi(w1, "log_pick_file") == 0) {
strcpy(log_config.log_pick, w2);
if(log_config.filter > 0 && !log_config.sql_logs)
- ShowNotice("Logging Item Picks to file `%s`.txt\n", w2);
+ ShowNotice("Logging Item Picks to file `%s`\n", w2);
} else if(strcmpi(w1, "log_zeny_file") == 0) {
strcpy(log_config.log_zeny, w2);
if(log_config.zeny > 0 && !log_config.sql_logs)
- ShowNotice("Logging Zeny to file `%s`.txt\n", w2);
+ ShowNotice("Logging Zeny to file `%s`\n", w2);
} else if(strcmpi(w1, "log_mvpdrop_file") == 0) {
strcpy(log_config.log_mvpdrop, w2);
if(log_config.mvpdrop > 0 && !log_config.sql_logs)
- ShowNotice("Logging MVP Drops to file `%s`.txt\n", w2);
+ ShowNotice("Logging MVP Drops to file `%s`\n", w2);
} else if(strcmpi(w1, "log_gm_file") == 0) {
strcpy(log_config.log_gm, w2);
if(log_config.gm > 0 && !log_config.sql_logs)
- ShowNotice("Logging GM Level %d Commands to file `%s`.txt\n", log_config.gm, w2);
+ ShowNotice("Logging GM Level %d Commands to file `%s`\n", log_config.gm, w2);
} else if(strcmpi(w1, "log_npc_file") == 0) {
strcpy(log_config.log_npc, w2);
if(log_config.npc > 0 && !log_config.sql_logs)
- ShowNotice("Logging NPC 'logmes' to file `%s`.txt\n", w2);
+ ShowNotice("Logging NPC 'logmes' to file `%s`\n", w2);
} else if(strcmpi(w1, "log_chat_file") == 0) {
strcpy(log_config.log_chat, w2);
if(log_config.chat > 0 && !log_config.sql_logs)
- ShowNotice("Logging CHAT to file `%s`.txt\n", w2);
+ ShowNotice("Logging CHAT to file `%s`\n", w2);
//support the import command, just like any other config
} else if(strcmpi(w1,"import") == 0) {
log_config_read(w2);
diff --git a/src/map/log.h b/src/map/log.h
index 9dfc0c0ea..f88236489 100644
--- a/src/map/log.h
+++ b/src/map/log.h
@@ -36,9 +36,10 @@ typedef enum log_what {
LOG_USED_ITEMS = 0x0100, // used by player
LOG_MVP_PRIZE = 0x0200,
LOG_COMMAND_ITEMS = 0x0400, // created/deleted through @/# commands
- LOG_STORAGE_ITEMS = 0x0800, // placed/retrieved from storage
- LOG_GSTORAGE_ITEMS = 0x1000, // placed/retrieved from guild storage
- LOG_MAILS = 0x2000 // mail system transactions
+ LOG_STORAGE_ITEMS = 0x0800, // placed/retrieved from storage
+ LOG_GSTORAGE_ITEMS = 0x1000, // placed/retrieved from guild storage
+ LOG_MAILS = 0x2000, // mail system transactions
+ LOG_BUYING_STORE = 0x4000, // buying store transactions
} log_what;
extern struct Log_Config {
diff --git a/src/map/mail.c b/src/map/mail.c
index f0869185a..c866bfb60 100644
--- a/src/map/mail.c
+++ b/src/map/mail.c
@@ -162,7 +162,7 @@ int mail_openmail(struct map_session_data *sd)
{
nullpo_ret(sd);
- if( sd->state.storage_flag || sd->vender_id || sd->state.trading )
+ if( sd->state.storage_flag || sd->vender_id || sd->state.buyingstore || sd->state.trading )
return 0;
clif_Mail_window(sd->fd, 0);
diff --git a/src/map/map.c b/src/map/map.c
index e3cada963..2cd146ee4 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -2781,6 +2781,7 @@ void map_flags_init(void)
map[i].nocommand = 0; // nocommand mapflag level
map[i].bexp = 100; // per map base exp multiplicator
map[i].jexp = 100; // per map job exp multiplicator
+ memset(map[i].drop_list, 0, sizeof(map[i].drop_list)); // pvp nightmare drop list
// adjustments
if( battle_config.pk_mode )
diff --git a/src/map/npc.c b/src/map/npc.c
index 1bf5bd312..bc2018459 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2263,6 +2263,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
char srcname[128];
int i;
const char* end;
+ size_t length;
int src_id;
int type;
@@ -2270,12 +2271,16 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
struct npc_data* dnd;
end = strchr(start,'\n');
+ length = strlen(w2);
+
// get the npc being duplicated
- if( sscanf(w2,"duplicate(%127[^)])",srcname) != 1 )
- {
+ if( w2[length-1] != ')' || length <= 11 || length-11 >= sizeof(srcname) )
+ {// does not match 'duplicate(%127s)', name is empty or too long
ShowError("npc_parse_script: bad duplicate name in file '%s', line '%d' : %s\n", filepath, strline(buffer,start-buffer), w2);
return end;// next line, try to continue
}
+ safestrncpy(srcname, w2+10, length-10);
+
dnd = npc_name2id(srcname);
if( dnd == NULL) {
ShowError("npc_parse_script: original npc not found for duplicate in file '%s', line '%d' : %s\n", filepath, strline(buffer,start-buffer), srcname);
diff --git a/src/map/party.c b/src/map/party.c
index 9c55a05f2..21867c95a 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -309,8 +309,8 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
return 0;
}
- if ( (pc_isGM(sd) > battle_config.lowest_gm_level && pc_isGM(tsd) < battle_config.lowest_gm_level && !battle_config.gm_can_party && pc_isGM(sd) < battle_config.gm_cant_party_min_lv)
- || ( pc_isGM(sd) < battle_config.lowest_gm_level && pc_isGM(tsd) > battle_config.lowest_gm_level && !battle_config.gm_can_party && pc_isGM(tsd) < battle_config.gm_cant_party_min_lv) )
+ if ( (pc_isGM(sd) >= battle_config.lowest_gm_level && pc_isGM(tsd) < battle_config.lowest_gm_level && !battle_config.gm_can_party && pc_isGM(sd) < battle_config.gm_cant_party_min_lv)
+ || ( pc_isGM(sd) < battle_config.lowest_gm_level && pc_isGM(tsd) >= battle_config.lowest_gm_level && !battle_config.gm_can_party && pc_isGM(tsd) < battle_config.gm_cant_party_min_lv) )
{
//GMs can't invite non GMs to the party if not above the invite trust level
//Likewise, as long as gm_can_party is off, players can't invite GMs.
diff --git a/src/map/pc.c b/src/map/pc.c
index 7525ff63c..ffbd2d3cf 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -893,6 +893,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
sd->state.showdelay = 1;
pc_setinventorydata(sd);
+ pc_setequipindex(sd);
status_change_init(&sd->bl);
if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) && (pc_isGM(sd) >= get_atcommand_level(atcommand_hide)))
@@ -1540,7 +1541,7 @@ static int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id,
if (!(flag&(ATF_TARGET|ATF_SELF)))
flag|=ATF_TARGET; //Default target: enemy.
if (!(flag&(ATF_WEAPON|ATF_MAGIC|ATF_MISC)))
- flag|=ATF_WEAPON; //Defatul type: weapon.
+ flag|=ATF_WEAPON; //Default type: weapon.
for (i = 0; i < max && effect[i].flag; i++) {
if (effect[i].id == id && effect[i].flag == flag)
@@ -2934,7 +2935,7 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
break;
}
if( sd->state.lr_flag != 2 )
- pc_bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, val, type2, 2);
+ pc_bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, val, type2, ATF_TARGET);
break;
case SP_ADDELE:
@@ -5047,7 +5048,7 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int
if(sd->state.showexp) {
char output[256];
sprintf(output,
- "Experience Gained Base:%u (%.2f%%) Job:%u (%.2f%%)", base_exp, nextbp*(float)100, job_exp, nextjp*(float)100);
+ "Experience Gained Base:%u (%.2f%%) Job:%u (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100);
clif_disp_onlyself(sd,output,strlen(output));
}
@@ -7875,7 +7876,7 @@ int duel_create(struct map_session_data* sd, const unsigned int maxpl)
strcpy(output, msg_txt(372)); // " -- Duel has been created (@invite/@leave) --"
clif_disp_onlyself(sd, output, strlen(output));
- clif_set0199(sd, 1);
+ clif_map_property(sd, MAPPROPERTY_FREEPVPZONE);
//clif_misceffect2(&sd->bl, 159);
return i;
}
@@ -7922,7 +7923,7 @@ int duel_leave(const unsigned int did, struct map_session_data* sd)
sd->duel_group = 0;
duel_savetime(sd);
- clif_set0199(sd, 0);
+ clif_map_property(sd, MAPPROPERTY_NOTHING);
return 0;
}
@@ -7939,7 +7940,7 @@ int duel_accept(const unsigned int did, struct map_session_data* sd)
sprintf(output, msg_txt(376), sd->status.name);
clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
- clif_set0199(sd, 1);
+ clif_map_property(sd, MAPPROPERTY_FREEPVPZONE);
//clif_misceffect2(&sd->bl, 159);
return 0;
}
diff --git a/src/map/pc.h b/src/map/pc.h
index c48defbf5..b9ccf3e88 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -7,10 +7,12 @@
#include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus
#include "../common/timer.h" // INVALID_TIMER
#include "battle.h" // battle_config
+#include "buyingstore.h" // struct s_buyingstore
#include "itemdb.h" // MAX_ITEMGROUP
#include "map.h" // RC_MAX
#include "pc.h" // struct map_session_data
#include "script.h" // struct script_reg, struct script_regstr
+#include "searchstore.h" // struct s_search_store_info
#include "status.h" // OPTION_*, struct weapon_atk
#include "unit.h" // unit_stop_attack(), unit_stop_walking()
#include "vending.h" // struct s_vending
@@ -104,7 +106,6 @@ struct map_session_data {
unsigned gangsterparadise : 1;
unsigned rest : 1;
unsigned storage_flag : 2; //0: closed, 1: Normal Storage open, 2: guild storage open [Skotlex]
- unsigned snovice_call_flag : 2; //Summon Angel (stage 1~3)
unsigned snovice_dead_flag : 1; //Explosion spirits on death: 0 off, 1 used.
unsigned abra_flag : 1; // Abracadabra bugfix by Aru
unsigned autocast : 1; // Autospell flag [Inkfish]
@@ -128,6 +129,7 @@ struct map_session_data {
unsigned doridori : 1;
unsigned ignoreAll : 1;
unsigned debug_remove_map : 1; // temporary state to track double remove_map's [FlavioJS]
+ unsigned buyingstore : 1;
unsigned short autoloot;
unsigned short autolootid; // [Zephyrus]
unsigned noks : 3; // [Zeph Kill Steal Protection]
@@ -356,6 +358,11 @@ struct map_session_data {
char message[MESSAGE_SIZE];
struct s_vending vending[MAX_VENDING];
+ unsigned int buyer_id; // uid of open buying store
+ struct s_buyingstore buyingstore;
+
+ struct s_search_store_info searchstore;
+
struct pet_data *pd;
struct homun_data *hd; // [blackhole89]
struct mercenary_data *md;
@@ -413,8 +420,8 @@ struct map_session_data {
const char* debug_func;
};
-//Update this max as necessary. 54 is the value needed for Super Baby currently
-#define MAX_SKILL_TREE 54
+//Update this max as necessary. 55 is the value needed for Super Baby currently
+#define MAX_SKILL_TREE 55
//Total number of classes (for data storage)
#define CLASS_COUNT (JOB_MAX - JOB_NOVICE_HIGH + JOB_MAX_BASIC)
@@ -515,9 +522,9 @@ extern int duel_count;
#define pc_setsit(sd) ( (sd)->state.dead_sit = (sd)->vd.dead_sit = 2 )
#define pc_isdead(sd) ( (sd)->state.dead_sit == 1 )
#define pc_issit(sd) ( (sd)->vd.dead_sit == 2 )
-#define pc_isidle(sd) ( (sd)->chatID || (sd)->vender_id || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.idle_no_share )
-#define pc_istrading(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->state.trading )
-#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->chatID || (sd)->sc.opt1 || (sd)->state.trading || (sd)->state.storage_flag )
+#define pc_isidle(sd) ( (sd)->chatID || (sd)->vender_id || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.idle_no_share )
+#define pc_istrading(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->state.buyingstore || (sd)->state.trading )
+#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->state.buyingstore || (sd)->chatID || (sd)->sc.opt1 || (sd)->state.trading || (sd)->state.storage_flag )
#define pc_setdir(sd,b,h) ( (sd)->ud.dir = (b) ,(sd)->head_dir = (h) )
#define pc_setchatid(sd,n) ( (sd)->chatID = n )
#define pc_ishiding(sd) ( (sd)->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) )
diff --git a/src/map/script.c b/src/map/script.c
index f842b614a..dec4a3f89 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -483,7 +483,14 @@ static void script_reportdata(struct script_data* data)
break;
case C_STR:
case C_CONSTSTR:// string
- ShowDebug("Data: string value=\"%s\"\n", data->u.str);
+ if( data->u.str )
+ {
+ ShowDebug("Data: string value=\"%s\"\n", data->u.str);
+ }
+ else
+ {
+ ShowDebug("Data: string value=NULL\n");
+ }
break;
case C_NAME:// reference
if( reference_tovariable(data) )
@@ -1253,7 +1260,9 @@ const char* parse_curly_close(const char* p)
set_label(l,script_pos, p);
linkdb_final(&syntax.curly[pos].case_label); // free the list of case label
syntax.curly_count--;
- return p+1;
+ // if, for , while ‚̕‚¶”»’è
+ p = parse_syntax_close(p + 1);
+ return p;
} else {
disp_error_message("parse_curly_close: unexpected string",p);
return p + 1;
@@ -1341,10 +1350,8 @@ const char* parse_syntax(const char* p)
v = p2-p; // length of word at p2
memcpy(label,p,v);
label[v]='\0';
- v = search_str(label);
- if (v < 0 || str_data[v].type != C_INT)
+ if( !script_get_constant(label, &v) )
disp_error_message("parse_syntax: 'case' label not integer",p);
- v = str_data[v].val;
p = skip_word(p);
} else { //Numeric value
if((*p == '-' || *p == '+') && ISDIGIT(p[1])) // pre-skip because '-' can not skip_word
@@ -1916,6 +1923,40 @@ static void add_buildin_func(void)
}
}
+/// Retrieves the value of a constant.
+bool script_get_constant(const char* name, int* value)
+{
+ int n = search_str(name);
+
+ if( n == -1 || str_data[n].type != C_INT )
+ {// not found or not a constant
+ return false;
+ }
+ value[0] = str_data[n].val;
+
+ return true;
+}
+
+/// Creates new constant or parameter with given value.
+void script_set_constant(const char* name, int value, bool isparameter)
+{
+ int n = add_str(name);
+
+ if( str_data[n].type == C_NOP )
+ {// new
+ str_data[n].type = isparameter ? C_PARAM : C_INT;
+ str_data[n].val = value;
+ }
+ else if( str_data[n].type == C_PARAM || str_data[n].type == C_INT )
+ {// existing parameter or constant
+ ShowError("script_set_constant: Attempted to overwrite existing %s '%s' (old value=%d, new value=%d).\n", ( str_data[n].type == C_PARAM ) ? "parameter" : "constant", name, str_data[n].val, value);
+ }
+ else
+ {// existing name
+ ShowError("script_set_constant: Invalid name for %s '%s' (already defined as %s).\n", isparameter ? "parameter" : "constant", name, script_op2name(str_data[n].type));
+ }
+}
+
/*==========================================
* ’蔃f[ƒ^ƒx[ƒX‚Ì“Ç‚Ýž‚Ý
*------------------------------------------*/
@@ -1923,7 +1964,7 @@ static void read_constdb(void)
{
FILE *fp;
char line[1024],name[1024],val[1024];
- int n,type;
+ int type;
sprintf(line, "%s/const.txt", db_path);
fp=fopen(line, "r");
@@ -1938,12 +1979,7 @@ static void read_constdb(void)
type=0;
if(sscanf(line,"%[A-Za-z0-9_],%[-0-9xXA-Fa-f],%d",name,val,&type)>=2 ||
sscanf(line,"%[A-Za-z0-9_] %[-0-9xXA-Fa-f] %d",name,val,&type)>=2){
- n=add_str(name);
- if(type==0)
- str_data[n].type=C_INT;
- else
- str_data[n].type=C_PARAM;
- str_data[n].val= (int)strtol(val,NULL,0);
+ script_set_constant(name, (int)strtol(val, NULL, 0), (bool)type);
}
}
fclose(fp);
@@ -5336,6 +5372,7 @@ BUILDIN_FUNC(countitem)
{
int nameid, i;
int count = 0;
+ struct item_data* id = NULL;
struct script_data* data;
TBL_PC* sd = script_rid2sd(st);
@@ -5345,24 +5382,26 @@ BUILDIN_FUNC(countitem)
}
data = script_getdata(st,2);
- get_val(st,data);
- if( data_isstring(data) ) {
- const char* name = conv_str(st,data);
- struct item_data* item_data;
- if((item_data = itemdb_searchname(name)) != NULL)
- nameid = item_data->nameid;
- else
- nameid = 0;
- } else
- nameid = conv_num(st,data);
+ get_val(st, data); // convert into value in case of a variable
- if (nameid < 500) {
- ShowError("wrong item ID : countitem(%i)\n", nameid);
- script_reportsrc(st);
+ if( data_isstring(data) )
+ {// item name
+ id = itemdb_searchname(conv_str(st, data));
+ }
+ else
+ {// item id
+ id = itemdb_exists(conv_num(st, data));
+ }
+
+ if( id == NULL )
+ {
+ ShowError("buildin_countitem: Invalid item '%s'.\n", script_getstr(st,2)); // returns string, regardless of what it was
script_pushint(st,0);
return 1;
}
+ nameid = id->nameid;
+
for(i = 0; i < MAX_INVENTORY; i++)
if(sd->status.inventory[i].nameid == nameid)
count += sd->status.inventory[i].amount;
@@ -5379,7 +5418,8 @@ BUILDIN_FUNC(countitem2)
{
int nameid, iden, ref, attr, c1, c2, c3, c4;
int count = 0;
- int i;
+ int i;
+ struct item_data* id = NULL;
struct script_data* data;
TBL_PC* sd = script_rid2sd(st);
@@ -5387,19 +5427,27 @@ BUILDIN_FUNC(countitem2)
script_pushint(st,0);
return 0;
}
-
+
data = script_getdata(st,2);
- get_val(st,data);
- if( data_isstring(data) ) {
- const char* name = conv_str(st,data);
- struct item_data* item_data;
- if((item_data = itemdb_searchname(name)) != NULL)
- nameid = item_data->nameid;
- else
- nameid = 0;
- } else
- nameid = conv_num(st,data);
-
+ get_val(st, data); // convert into value in case of a variable
+
+ if( data_isstring(data) )
+ {// item name
+ id = itemdb_searchname(conv_str(st, data));
+ }
+ else
+ {// item id
+ id = itemdb_exists(conv_num(st, data));
+ }
+
+ if( id == NULL )
+ {
+ ShowError("buildin_countitem2: Invalid item '%s'.\n", script_getstr(st,2)); // returns string, regardless of what it was
+ script_pushint(st,0);
+ return 1;
+ }
+
+ nameid = id->nameid;
iden = script_getnum(st,3);
ref = script_getnum(st,4);
attr = script_getnum(st,5);
@@ -5407,13 +5455,7 @@ BUILDIN_FUNC(countitem2)
c2 = (short)script_getnum(st,7);
c3 = (short)script_getnum(st,8);
c4 = (short)script_getnum(st,9);
-
- if (nameid < 500) {
- ShowError("wrong item ID : countitem2(%i)\n", nameid);
- script_pushint(st,0);
- return 1;
- }
-
+
for(i = 0; i < MAX_INVENTORY; i++)
if (sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] != NULL &&
sd->status.inventory[i].amount > 0 && sd->status.inventory[i].nameid == nameid &&
@@ -5652,7 +5694,7 @@ BUILDIN_FUNC(getitem2)
if (item_data == NULL)
return -1;
if(item_data->type==IT_WEAPON || item_data->type==IT_ARMOR){
- if(ref > 10) ref = 10;
+ if(ref > MAX_REFINE) ref = MAX_REFINE;
}
else if(item_data->type==IT_PETEGG) {
iden = 1;
@@ -9089,6 +9131,11 @@ BUILDIN_FUNC(birthpet)
if( sd == NULL )
return 0;
+ if( sd->status.pet_id )
+ {// do not send egg list, when you already have a pet
+ return 0;
+ }
+
clif_sendegg(sd);
return 0;
}
@@ -9745,7 +9792,7 @@ BUILDIN_FUNC(pvpon)
return 0; // nothing to do
map[m].flag.pvp = 1;
- clif_send0199(m,1);
+ clif_map_property_mapall(m, MAPPROPERTY_FREEPVPZONE);
if(battle_config.pk_mode) // disable ranking functions if pk_mode is on [Valaris]
return 0;
@@ -9790,7 +9837,7 @@ BUILDIN_FUNC(pvpoff)
return 0; //fixed Lupus
map[m].flag.pvp = 0;
- clif_send0199(m,0);
+ clif_map_property_mapall(m, MAPPROPERTY_NOTHING);
if(battle_config.pk_mode) // disable ranking options if pk_mode is on [Valaris]
return 0;
@@ -9808,7 +9855,7 @@ BUILDIN_FUNC(gvgon)
m = map_mapname2mapid(str);
if(m >= 0 && !map[m].flag.gvg) {
map[m].flag.gvg = 1;
- clif_send0199(m,3);
+ clif_map_property_mapall(m, MAPPROPERTY_AGITZONE);
}
return 0;
@@ -9822,7 +9869,7 @@ BUILDIN_FUNC(gvgoff)
m = map_mapname2mapid(str);
if(m >= 0 && map[m].flag.gvg) {
map[m].flag.gvg = 0;
- clif_send0199(m,0);
+ clif_map_property_mapall(m, MAPPROPERTY_NOTHING);
}
return 0;
@@ -11773,17 +11820,17 @@ BUILDIN_FUNC(message)
BUILDIN_FUNC(npctalk)
{
const char* str;
- char message[255];
+ char name[NAME_LENGTH], message[256];
struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid);
str = script_getstr(st,2);
- if(nd) {
- memcpy(message, nd->name, NAME_LENGTH);
- strtok(message, "#"); // discard extra name identifier if present
- strcat(message, " : ");
- strncat(message, str, 254); //Prevent overflow possibility. [Skotlex]
- clif_message(&(nd->bl), message);
+ if(nd)
+ {
+ safestrncpy(name, nd->name, sizeof(name));
+ strtok(name, "#"); // discard extra name identifier if present
+ safesnprintf(message, sizeof(message), "%s : %s", name, str);
+ clif_message(&nd->bl, message);
}
return 0;
@@ -12357,9 +12404,20 @@ BUILDIN_FUNC(autoequip)
struct item_data *item_data;
nameid=script_getnum(st,2);
flag=script_getnum(st,3);
- if(nameid>=500 && (item_data = itemdb_exists(nameid)) != NULL){
- item_data->flag.autoequip = flag>0?1:0;
+
+ if( ( item_data = itemdb_exists(nameid) ) == NULL )
+ {
+ ShowError("buildin_autoequip: Invalid item '%d'.\n", nameid);
+ return 1;
+ }
+
+ if( !itemdb_isequip2(item_data) )
+ {
+ ShowError("buildin_autoequip: Item '%d' cannot be equipped.\n", nameid);
+ return 1;
}
+
+ item_data->flag.autoequip = flag>0?1:0;
return 0;
}
@@ -14635,9 +14693,6 @@ static int buildin_mobuseskill_sub(struct block_list *bl,va_list ap)
if( md->class_ != mobid )
return 0;
- if( md->ud.skilltimer != INVALID_TIMER ) // Cancel the casting skill.
- unit_skillcastcancel(bl,0);
-
// 0:self, 1:target, 2:master, default:random
switch( target )
{
@@ -14650,6 +14705,9 @@ static int buildin_mobuseskill_sub(struct block_list *bl,va_list ap)
if( !tbl )
return 0;
+ if( md->ud.skilltimer != INVALID_TIMER ) // Cancel the casting skill.
+ unit_skillcastcancel(bl,0);
+
if( skill_get_casttype(skillid) == CAST_GROUND )
unit_skilluse_pos2(&md->bl, tbl->x, tbl->y, skillid, skilllv, casttime, cancel);
else
@@ -14756,6 +14814,56 @@ BUILDIN_FUNC(pushpc)
return 0;
}
+
+/// Invokes buying store preparation window
+/// buyingstore <slots>;
+BUILDIN_FUNC(buyingstore)
+{
+ struct map_session_data* sd;
+
+ if( ( sd = script_rid2sd(st) ) == NULL )
+ {
+ return 0;
+ }
+
+ buyingstore_setup(sd, script_getnum(st,2));
+ return 0;
+}
+
+
+/// Invokes search store info window
+/// searchstores <uses>,<effect>;
+BUILDIN_FUNC(searchstores)
+{
+ unsigned short effect;
+ unsigned int uses;
+ struct map_session_data* sd;
+
+ if( ( sd = script_rid2sd(st) ) == NULL )
+ {
+ return 0;
+ }
+
+ uses = script_getnum(st,2);
+ effect = script_getnum(st,3);
+
+ if( !uses )
+ {
+ ShowError("buildin_searchstores: Amount of uses cannot be zero.\n");
+ return 1;
+ }
+
+ if( effect > 1 )
+ {
+ ShowError("buildin_searchstores: Invalid effect id %hu, specified.\n", effect);
+ return 1;
+ }
+
+ searchstore_open(sd, uses, effect);
+ return 0;
+}
+
+
// declarations that were supposed to be exported from npc_chat.c
#ifdef PCRE_SUPPORT
BUILDIN_FUNC(defpattern);
@@ -15117,6 +15225,8 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(areamobuseskill,"siiiiviiiii"),
BUILDIN_DEF(progressbar,"si"),
BUILDIN_DEF(pushpc,"ii"),
+ BUILDIN_DEF(buyingstore,"i"),
+ BUILDIN_DEF(searchstores,"ii"),
// WoE SE
BUILDIN_DEF(agitstart2,""),
BUILDIN_DEF(agitend2,""),
diff --git a/src/map/script.h b/src/map/script.h
index d6ede0e8b..c272f2d32 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -167,6 +167,9 @@ struct DBMap* script_get_label_db(void);
struct DBMap* script_get_userfunc_db(void);
void script_run_autobonus(const char *autobonus,int id, int pos);
+bool script_get_constant(const char* name, int* value);
+void script_set_constant(const char* name, int value, bool isparameter);
+
void script_cleararray_pc(struct map_session_data* sd, const char* varname, void* value);
void script_setarray_pc(struct map_session_data* sd, const char* varname, uint8 idx, void* value, int* refcache);
diff --git a/src/map/searchstore.c b/src/map/searchstore.c
new file mode 100644
index 000000000..d7378ab36
--- /dev/null
+++ b/src/map/searchstore.c
@@ -0,0 +1,405 @@
+// 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" // aMalloc, aRealloc, aFree
+#include "../common/showmsg.h" // ShowError, ShowWarning
+#include "../common/strlib.h" // safestrncpy
+#include "battle.h" // battle_config.*
+#include "clif.h" // clif_open_search_store_info, clif_search_store_info_*
+#include "pc.h" // struct map_session_data
+#include "searchstore.h" // struct s_search_store_info
+
+
+/// failure constants for clif functions
+enum e_searchstore_failure
+{
+ SSI_FAILED_NOTHING_SEARCH_ITEM = 0, // "No matching stores were found."
+ SSI_FAILED_OVER_MAXCOUNT = 1, // "There are too many results. Please enter more detailed search term."
+ SSI_FAILED_SEARCH_CNT = 2, // "You cannot search anymore."
+ SSI_FAILED_LIMIT_SEARCH_TIME = 3, // "You cannot search yet."
+ SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE = 4, // "No sale (purchase) information available."
+};
+
+
+enum e_searchstore_searchtype
+{
+ SEARCHTYPE_VENDING = 0,
+ SEARCHTYPE_BUYING_STORE = 1,
+};
+
+
+enum e_searchstore_effecttype
+{
+ EFFECTTYPE_NORMAL = 0,
+ EFFECTTYPE_CASH = 1,
+ EFFECTTYPE_MAX
+};
+
+
+/// type for shop search function
+typedef bool (*searchstore_search_t)(struct map_session_data* sd, unsigned short nameid);
+typedef bool (*searchstore_searchall_t)(struct map_session_data* sd, const struct s_search_store_search* s);
+
+
+/// retrieves search function by type
+static searchstore_search_t searchstore_getsearchfunc(unsigned char type)
+{
+ switch( type )
+ {
+ case SEARCHTYPE_VENDING: return &vending_search;
+ case SEARCHTYPE_BUYING_STORE: return &buyingstore_search;
+ }
+ return NULL;
+}
+
+
+/// retrieves search-all function by type
+static searchstore_searchall_t searchstore_getsearchallfunc(unsigned char type)
+{
+ switch( type )
+ {
+ case SEARCHTYPE_VENDING: return &vending_searchall;
+ case SEARCHTYPE_BUYING_STORE: return &buyingstore_searchall;
+ }
+ return NULL;
+}
+
+
+/// checks if the player has a store by type
+static bool searchstore_hasstore(struct map_session_data* sd, unsigned char type)
+{
+ switch( type )
+ {
+ case SEARCHTYPE_VENDING: return (bool)( sd->vender_id != 0 );
+ case SEARCHTYPE_BUYING_STORE: return sd->state.buyingstore;
+ }
+ return false;
+}
+
+
+/// returns player's store id by type
+static int searchstore_getstoreid(struct map_session_data* sd, unsigned char type)
+{
+ switch( type )
+ {
+ case SEARCHTYPE_VENDING: return sd->vender_id;
+ case SEARCHTYPE_BUYING_STORE: return sd->buyer_id;
+ }
+ return 0;
+}
+
+
+bool searchstore_open(struct map_session_data* sd, unsigned int uses, unsigned short effect)
+{
+ if( !battle_config.feature_search_stores || sd->searchstore.open )
+ {
+ return false;
+ }
+
+ if( !uses || effect >= EFFECTTYPE_MAX )
+ {// invalid input
+ return false;
+ }
+
+ sd->searchstore.open = true;
+ sd->searchstore.uses = uses;
+ sd->searchstore.effect = effect;
+
+ clif_open_search_store_info(sd);
+
+ return true;
+}
+
+
+void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count)
+{
+ unsigned int i;
+ struct map_session_data* pl_sd;
+ struct s_mapiterator* iter;
+ struct s_search_store_search s;
+ searchstore_searchall_t store_searchall;
+ time_t querytime;
+
+ if( !battle_config.feature_search_stores )
+ {
+ return;
+ }
+
+ if( !sd->searchstore.open )
+ {
+ return;
+ }
+
+ if( ( store_searchall = searchstore_getsearchallfunc(type) ) == NULL )
+ {
+ ShowError("searchstore_query: Unknown search type %u (account_id=%d).\n", (unsigned int)type, sd->bl.id);
+ return;
+ }
+
+ time(&querytime);
+
+ if( sd->searchstore.nextquerytime > querytime )
+ {
+ clif_search_store_info_failed(sd, SSI_FAILED_LIMIT_SEARCH_TIME);
+ return;
+ }
+
+ if( !sd->searchstore.uses )
+ {
+ clif_search_store_info_failed(sd, SSI_FAILED_SEARCH_CNT);
+ return;
+ }
+
+ // validate lists
+ for( i = 0; i < item_count; i++ )
+ {
+ if( !itemdb_exists(itemlist[i]) )
+ {
+ ShowWarning("searchstore_query: Client resolved item %hu is not known.\n", itemlist[i]);
+ clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM);
+ return;
+ }
+ }
+ for( i = 0; i < card_count; i++ )
+ {
+ if( !itemdb_exists(cardlist[i]) )
+ {
+ ShowWarning("searchstore_query: Client resolved card %hu is not known.\n", cardlist[i]);
+ clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM);
+ return;
+ }
+ }
+
+ if( max_price < min_price )
+ {
+ swap(min_price, max_price);
+ }
+
+ sd->searchstore.uses--;
+ sd->searchstore.type = type;
+ sd->searchstore.nextquerytime = querytime+battle_config.searchstore_querydelay;
+
+ // drop previous results
+ searchstore_clear(sd);
+
+ // allocate max. amount of results
+ sd->searchstore.items = aMalloc(sizeof(struct s_search_store_info_item)*battle_config.searchstore_maxresults);
+
+ // search
+ s.search_sd = sd;
+ s.itemlist = itemlist;
+ s.cardlist = cardlist;
+ s.item_count = item_count;
+ s.card_count = card_count;
+ s.min_price = min_price;
+ s.max_price = max_price;
+ iter = mapit_geteachpc();
+
+ for( pl_sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); pl_sd = (struct map_session_data*)mapit_next(iter) )
+ {
+ if( sd == pl_sd )
+ {// skip own shop, if any
+ continue;
+ }
+
+ if( !store_searchall(pl_sd, &s) )
+ {// exceeded result size
+ clif_search_store_info_failed(sd, SSI_FAILED_OVER_MAXCOUNT);
+ break;
+ }
+ }
+
+ mapit_free(iter);
+
+ if( sd->searchstore.count )
+ {
+ // reclaim unused memory
+ sd->searchstore.items = aRealloc(sd->searchstore.items, sizeof(struct s_search_store_info_item)*sd->searchstore.count);
+
+ // present results
+ clif_search_store_info_ack(sd);
+
+ // one page displayed
+ sd->searchstore.pages++;
+ }
+ else
+ {
+ // cleanup
+ searchstore_clear(sd);
+
+ // update uses
+ clif_search_store_info_ack(sd);
+
+ // notify of failure
+ clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM);
+ }
+}
+
+
+/// checks whether or not more results are available for the client
+bool searchstore_querynext(struct map_session_data* sd)
+{
+ if( sd->searchstore.count && ( sd->searchstore.count-1 )/SEARCHSTORE_RESULTS_PER_PAGE < sd->searchstore.pages )
+ {
+ return true;
+ }
+
+ return false;
+}
+
+
+void searchstore_next(struct map_session_data* sd)
+{
+ if( !battle_config.feature_search_stores || !sd->searchstore.open || sd->searchstore.count <= sd->searchstore.pages*SEARCHSTORE_RESULTS_PER_PAGE )
+ {// nothing (more) to display
+ return;
+ }
+
+ // present results
+ clif_search_store_info_ack(sd);
+
+ // one more page displayed
+ sd->searchstore.pages++;
+}
+
+
+void searchstore_clear(struct map_session_data* sd)
+{
+ searchstore_clearremote(sd);
+
+ if( sd->searchstore.items )
+ {// release results
+ aFree(sd->searchstore.items);
+ sd->searchstore.items = NULL;
+ }
+
+ sd->searchstore.count = 0;
+ sd->searchstore.pages = 0;
+}
+
+
+void searchstore_close(struct map_session_data* sd)
+{
+ if( sd->searchstore.open )
+ {
+ searchstore_clear(sd);
+
+ sd->searchstore.uses = 0;
+ sd->searchstore.open = false;
+ }
+}
+
+
+void searchstore_click(struct map_session_data* sd, int account_id, int store_id, unsigned short nameid)
+{
+ unsigned int i;
+ struct map_session_data* pl_sd;
+ searchstore_search_t store_search;
+
+ if( !battle_config.feature_search_stores || !sd->searchstore.open || !sd->searchstore.count )
+ {
+ return;
+ }
+
+ searchstore_clearremote(sd);
+
+ ARR_FIND( 0, sd->searchstore.count, i, sd->searchstore.items[i].store_id == store_id && sd->searchstore.items[i].account_id == account_id && sd->searchstore.items[i].nameid == nameid );
+ if( i == sd->searchstore.count )
+ {// no such result, crafted
+ ShowWarning("searchstore_click: Received request with item %hu of account %d, which is not part of current result set (account_id=%d, char_id=%d).\n", nameid, account_id, sd->bl.id, sd->status.char_id);
+ clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE);
+ return;
+ }
+
+ if( ( pl_sd = map_id2sd(account_id) ) == NULL )
+ {// no longer online
+ clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE);
+ return;
+ }
+
+ if( !searchstore_hasstore(pl_sd, sd->searchstore.type) || searchstore_getstoreid(pl_sd, sd->searchstore.type) != store_id )
+ {// no longer vending/buying or not same shop
+ clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE);
+ return;
+ }
+
+ store_search = searchstore_getsearchfunc(sd->searchstore.type);
+
+ if( !store_search(pl_sd, nameid) )
+ {// item no longer being sold/bought
+ clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE);
+ return;
+ }
+
+ switch( sd->searchstore.effect )
+ {
+ case EFFECTTYPE_NORMAL:
+ // display coords
+
+ if( sd->bl.m != pl_sd->bl.m )
+ {// not on same map, wipe previous marker
+ clif_search_store_info_click_ack(sd, -1, -1);
+ }
+ else
+ {
+ clif_search_store_info_click_ack(sd, pl_sd->bl.x, pl_sd->bl.y);
+ }
+
+ break;
+ case EFFECTTYPE_CASH:
+ // open remotely
+
+ // to bypass range checks
+ sd->searchstore.remote_id = account_id;
+
+ switch( sd->searchstore.type )
+ {
+ case SEARCHTYPE_VENDING: vending_vendinglistreq(sd, account_id); break;
+ case SEARCHTYPE_BUYING_STORE: buyingstore_open(sd, account_id); break;
+ }
+
+ break;
+ default:
+ // unknown
+ ShowError("searchstore_click: Unknown search store effect %u (account_id=%d).\n", (unsigned int)sd->searchstore.effect, sd->bl.id);
+ }
+}
+
+
+/// checks whether or not sd has opened account_id's shop remotely
+bool searchstore_queryremote(struct map_session_data* sd, int account_id)
+{
+ return (bool)( sd->searchstore.open && sd->searchstore.count && sd->searchstore.remote_id == account_id );
+}
+
+
+/// removes range-check bypassing for remotely opened stores
+void searchstore_clearremote(struct map_session_data* sd)
+{
+ sd->searchstore.remote_id = 0;
+}
+
+
+/// receives results from a store-specific callback
+bool searchstore_result(struct map_session_data* sd, int store_id, int account_id, const char* store_name, unsigned short nameid, unsigned short amount, unsigned int price, const short* card, unsigned char refine)
+{
+ struct s_search_store_info_item* ssitem;
+
+ if( sd->searchstore.count >= (unsigned int)battle_config.searchstore_maxresults )
+ {// no more
+ return false;
+ }
+
+ ssitem = &sd->searchstore.items[sd->searchstore.count++];
+ ssitem->store_id = store_id;
+ ssitem->account_id = account_id;
+ safestrncpy(ssitem->store_name, store_name, sizeof(ssitem->store_name));
+ ssitem->nameid = nameid;
+ ssitem->amount = amount;
+ ssitem->price = price;
+ memcpy(ssitem->card, card, sizeof(ssitem->card));
+ ssitem->refine = refine;
+
+ return true;
+}
diff --git a/src/map/searchstore.h b/src/map/searchstore.h
new file mode 100644
index 000000000..ffa8e9784
--- /dev/null
+++ b/src/map/searchstore.h
@@ -0,0 +1,57 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef _SEARCHSTORE_H_
+#define _SEARCHSTORE_H_
+
+#define SEARCHSTORE_RESULTS_PER_PAGE 10
+
+/// information about the search being performed
+struct s_search_store_search
+{
+ struct map_session_data* search_sd; // sd of the searching player
+ const unsigned short* itemlist;
+ const unsigned short* cardlist;
+ unsigned int item_count;
+ unsigned int card_count;
+ unsigned int min_price;
+ unsigned int max_price;
+};
+
+struct s_search_store_info_item
+{
+ int store_id;
+ int account_id;
+ char store_name[MESSAGE_SIZE];
+ unsigned short nameid;
+ unsigned short amount;
+ unsigned int price;
+ short card[MAX_SLOTS];
+ unsigned char refine;
+};
+
+struct s_search_store_info
+{
+ unsigned int count;
+ struct s_search_store_info_item* items;
+ unsigned int pages; // amount of pages already sent to client
+ unsigned int uses;
+ int remote_id;
+ time_t nextquerytime;
+ unsigned short effect; // 0 = Normal (display coords), 1 = Cash (remote open store)
+ unsigned char type; // 0 = Vending, 1 = Buying Store
+ bool open;
+};
+
+bool searchstore_open(struct map_session_data* sd, unsigned int uses, unsigned short effect);
+void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count);
+bool searchstore_querynext(struct map_session_data* sd);
+void searchstore_next(struct map_session_data* sd);
+void searchstore_clear(struct map_session_data* sd);
+void searchstore_close(struct map_session_data* sd);
+void searchstore_click(struct map_session_data* sd, int account_id, int store_id, unsigned short nameid);
+bool searchstore_queryremote(struct map_session_data* sd, int account_id);
+void searchstore_clearremote(struct map_session_data* sd);
+bool searchstore_result(struct map_session_data* sd, int store_id, int account_id, const char* store_name, unsigned short nameid, unsigned short amount, unsigned int price, const short* card, unsigned char refine);
+
+#endif // _SEARCHSTORE_H_
diff --git a/src/map/skill.c b/src/map/skill.c
index cd9115df4..160beeaef 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -5692,6 +5692,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case ALL_WEWISH:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
break;
+ case ALL_BUYING_STORE:
+ if( sd )
+ {// players only, skill allows 5 buying slots
+ clif_skill_nodamage(src, bl, skillid, skilllv, buyingstore_setup(sd, MAX_BUYINGSTORE_SLOTS));
+ }
+ break;
default:
ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skillid);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
@@ -6754,15 +6760,23 @@ int skill_dance_overlap(struct skill_unit* unit, int flag)
*------------------------------------------*/
static bool skill_dance_switch(struct skill_unit* unit, int flag)
{
+ static int prevflag = 1; // by default the backup is empty
static struct skill_unit_group backup;
struct skill_unit_group* group = unit->group;
- //TODO: add protection against attempts to read an empty backup / write to a full backup
-
// val2&UF_ENSEMBLE is a hack to indicate dissonance
if ( !(group->state.song_dance&0x1 && unit->val2&UF_ENSEMBLE) )
return false;
+ if( flag == prevflag )
+ {// protection against attempts to read an empty backup / write to a full backup
+ ShowError("skill_dance_switch: Attempted to %s (skill_id=%d, skill_lv=%d, src_id=%d).\n",
+ flag ? "read an empty backup" : "write to a full backup",
+ group->skill_id, group->skill_lv, group->src_id);
+ return false;
+ }
+ prevflag = flag;
+
if( !flag )
{ //Transform
int skillid = unit->val2&UF_SONG ? BA_DISSONANCE : DC_UGLYDANCE;
diff --git a/src/map/status.c b/src/map/status.c
index 45fe3a4cf..33da5fb14 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -174,7 +174,7 @@ void initChangeTables(void)
set_sc( BS_ADRENALINE , SC_ADRENALINE , SI_ADRENALINE , SCB_ASPD );
set_sc( BS_WEAPONPERFECT , SC_WEAPONPERFECTION, SI_WEAPONPERFECTION, SCB_NONE );
set_sc( BS_OVERTHRUST , SC_OVERTHRUST , SI_OVERTHRUST , SCB_NONE );
- set_sc( BS_MAXIMIZE , SC_MAXIMIZEPOWER , SI_MAXIMIZEPOWER , SCB_NONE );
+ set_sc( BS_MAXIMIZE , SC_MAXIMIZEPOWER , SI_MAXIMIZEPOWER , SCB_REGEN );
add_sc( HT_LANDMINE , SC_STUN );
add_sc( HT_ANKLESNARE , SC_ANKLE );
add_sc( HT_SANDMAN , SC_SLEEP );
@@ -2693,6 +2693,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
(((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK &&
(sc->data[SC_EXTREMITYFIST] || (sc->data[SC_EXPLOSIONSPIRITS] && (!sc->data[SC_SPIRIT] || sc->data[SC_SPIRIT]->val2 != SL_MONK)))
)
+ || sc->data[SC_MAXIMIZEPOWER]
) //No natural SP regen
regen->flag &=~RGN_SP;
@@ -6746,7 +6747,8 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
case SC_AUTOTRADE:
if (tid == INVALID_TIMER)
break;
- vending_closevending(sd);
+ // Note: vending/buying is closed by unit_remove_map, no
+ // need to do it here.
map_quit(sd);
// Because map_quit calls status_change_end with tid -1
// from here it's not neccesary to continue
diff --git a/src/map/trade.c b/src/map/trade.c
index ba01826f2..bedbb9451 100644
--- a/src/map/trade.c
+++ b/src/map/trade.c
@@ -138,8 +138,8 @@ void trade_tradeack(struct map_session_data *sd, int type)
}
//Check if you can start trade.
- if (sd->npc_id || sd->vender_id || sd->state.storage_flag ||
- tsd->npc_id || tsd->vender_id || tsd->state.storage_flag)
+ if (sd->npc_id || sd->vender_id || sd->state.buyingstore || sd->state.storage_flag ||
+ tsd->npc_id || tsd->vender_id || tsd->state.buyingstore || tsd->state.storage_flag)
{ //Fail
clif_tradestart(sd, 2);
clif_tradestart(tsd, 2);
diff --git a/src/map/unit.c b/src/map/unit.c
index 7abfde12b..2467baf86 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -803,6 +803,7 @@ int unit_can_move(struct block_list *bl)
if (sd && (
pc_issit(sd) ||
sd->vender_id ||
+ sd->state.buyingstore ||
sd->state.blockedmove
))
return 0; //Can't move
@@ -1872,6 +1873,8 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
trade_tradecancel(sd);
if(sd->vender_id)
vending_closevending(sd);
+ buyingstore_close(sd);
+ searchstore_close(sd);
if(sd->state.storage_flag == 1)
storage_storage_quit(sd,0);
else if (sd->state.storage_flag == 2)
diff --git a/src/map/vending.c b/src/map/vending.c
index a47be9057..08e15d733 100644
--- a/src/map/vending.c
+++ b/src/map/vending.c
@@ -87,8 +87,11 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
return;
}
- if( sd->bl.m != vsd->bl.m || !check_distance_bl(&sd->bl, &vsd->bl, AREA_SIZE) )
+ if( !searchstore_queryremote(sd, aid) && ( sd->bl.m != vsd->bl.m || !check_distance_bl(&sd->bl, &vsd->bl, AREA_SIZE) ) )
return; // shop too far away
+
+ searchstore_clearremote(sd);
+
if( count < 1 || count > MAX_VENDING || count > vsd->vend_num )
return; // invalid amount of purchased items
@@ -314,3 +317,88 @@ void vending_openvending(struct map_session_data* sd, const char* message, bool
clif_openvending(sd,sd->bl.id,sd->vending);
clif_showvendingboard(&sd->bl,message,0);
}
+
+
+/// Checks if an item is being sold in given player's vending.
+bool vending_search(struct map_session_data* sd, unsigned short nameid)
+{
+ int i;
+
+ if( !sd->vender_id )
+ {// not vending
+ return false;
+ }
+
+ ARR_FIND( 0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == (short)nameid );
+ if( i == sd->vend_num )
+ {// not found
+ return false;
+ }
+
+ return true;
+}
+
+
+/// Searches for all items in a vending, that match given ids, price and possible cards.
+/// @return Whether or not the search should be continued.
+bool vending_searchall(struct map_session_data* sd, const struct s_search_store_search* s)
+{
+ int i, c, slot;
+ unsigned int idx, cidx;
+ struct item* it;
+
+ if( !sd->vender_id )
+ {// not vending
+ return true;
+ }
+
+ for( idx = 0; idx < s->item_count; idx++ )
+ {
+ ARR_FIND( 0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == (short)s->itemlist[idx] );
+ if( i == sd->vend_num )
+ {// not found
+ continue;
+ }
+ it = &sd->status.cart[sd->vending[i].index];
+
+ if( s->min_price && s->min_price > sd->vending[i].value )
+ {// too low price
+ continue;
+ }
+
+ if( s->max_price && s->max_price < sd->vending[i].value )
+ {// too high price
+ continue;
+ }
+
+ if( s->card_count )
+ {// check cards
+ if( itemdb_isspecial(it->card[0]) )
+ {// something, that is not a carded
+ continue;
+ }
+ slot = itemdb_slot(it->nameid);
+
+ for( c = 0; c < slot && it->card[c]; c ++ )
+ {
+ ARR_FIND( 0, s->card_count, cidx, s->cardlist[cidx] == it->card[c] );
+ if( cidx != s->card_count )
+ {// found
+ break;
+ }
+ }
+
+ if( c == slot || !it->card[c] )
+ {// no card match
+ continue;
+ }
+ }
+
+ if( !searchstore_result(s->search_sd, sd->vender_id, sd->status.account_id, sd->message, it->nameid, sd->vending[i].amount, sd->vending[i].value, it->card, it->refine) )
+ {// result set full
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/src/map/vending.h b/src/map/vending.h
index 3c483a38c..6cfc90820 100644
--- a/src/map/vending.h
+++ b/src/map/vending.h
@@ -7,6 +7,7 @@
#include "../common/cbasetypes.h"
//#include "map.h"
struct map_session_data;
+struct s_search_store_search;
struct s_vending {
short index;
@@ -18,5 +19,7 @@ void vending_closevending(struct map_session_data* sd);
void vending_openvending(struct map_session_data* sd, const char* message, bool flag, const uint8* data, int count);
void vending_vendinglistreq(struct map_session_data* sd, int id);
void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count);
+bool vending_search(struct map_session_data* sd, unsigned short nameid);
+bool vending_searchall(struct map_session_data* sd, const struct s_search_store_search* s);
#endif /* _VENDING_H_ */
diff --git a/src/plugins/console.c b/src/plugins/console.c
index b1307f863..bf1a133ca 100644
--- a/src/plugins/console.c
+++ b/src/plugins/console.c
@@ -34,8 +34,7 @@
do{ \
DWORD dwThreadId; \
buf.worker = CreateThread(NULL, 0, worker_ ## name, NULL, CREATE_SUSPENDED, &dwThreadId); \
- if( errvar ) \
- *errvar = ( buf.worker == NULL ); \
+ *(errvar) = ( buf.worker == NULL ); \
}while(0)
/// Buffer for asynchronous input
@@ -61,8 +60,7 @@ typedef struct _buffer {
if( pid == 0 ){ \
worker_ ## name(); \
} \
- if( errvar ) \
- *errvar = (pid == -1); \
+ *(errvar) = (pid == -1); \
}while(0)
#define PIPE_READ 0
diff --git a/tools/getlogincount.pl b/tools/getlogincount.pl
deleted file mode 100755
index de075ed22..000000000
--- a/tools/getlogincount.pl
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/perl -w
-
-##########################################################################
-# INFORMATION TOOL ABOUT THE # OF ONLINE PLAYERS ON ATHENA SERVERS
-#
-# By connection on the athena login-server, this software displays the
-# number of online players.
-#
-#-------------------------------------------------------------------------
-# Software usage:
-# Configure the IP, the port and a valid account of the server.
-# After, use at your choice:
-# ./getlogincount.pl - display the number of online players on all servers.
-# ./getlogincount.pl --premier or
-# ./getlogincount.pl --first -- display the number of online players of the
-# first server in the received list.
-# ./getlogincount.pl [servername] -- display the number of online players
-# of the specified server.
-#
-# If successfull, the software return the value 0.
-#
-##########################################################################
-
-#------------------------------ CONFIGURATION ----------------------------
-
-$loginserverip = "127.0.0.1"; # IP of the login-server
-$loginserverport = 6900; # port of the login-server
-$loginaccount = "s1"; # a valid account name
-$loginpasswd = "p1"; # the password of the valid account name
-
-$connecttimeout = 10; # Connection timeout (in seconds)
-
-#-------------------------------------------------------------------------
-
-use IO::Socket;
-
-my($sname) = $ARGV[0];
-if (!defined($sname)) {
- $sname = "";
-}
-
-# Connection to the login-server
-my($so,$er) = ();
-eval{
- $so = IO::Socket::INET->new(
- PeerAddr=> $loginserverip,
- PeerPort=> $loginserverport,
- Proto => "tcp",
- Timeout => $connecttimeout) or $er=1;
-};
-if($er || $@){
- print "Can't not connect to the login-server [${loginserverip}:$loginserverport] !\n";
- exit(2);
-}
-
-# Request to connect on login-server
-print $so pack("v V a24 a24 C",0x0064,9,$loginaccount,$loginpasswd,3);
-$so->flush();
-
-# Fail to connect
-if(unpack("v", &soread(\$so,2)) != 0x0069) {
- print "Login error.\n";
- exit(3);
-}
-
-# Get length of the received packet
-my($plen) = unpack("v",&soread(\$so,2))-4;
-
-# Suppress information of the account (we need only information about the servers)
-&soread(\$so,43);
-$plen -= 43;
-
-# Check about the number of online servers
-if ($plen < 32) {
- printf "No server is connected to login-server.\n";
- exit(1);
-}
-
-# Read information of the servers
-my(@slist) = ();
-for(;$plen > 0;$plen -= 32) {
- my($name,$count) = unpack("x6 a20 V",&soread(\$so,32));
- $name = substr($name,0,index($name,"\0"));
- push @slist, [ $name, $count ];
-}
-
-# Display the result
-if($sname eq "--first" || $sname eq "--premier") { # If we ask only for the first server
- printf "%-20s : %5d\n",$slist[0][0],$slist[0][1];
-} elsif ($sname eq "") { # If we ask for all servers
- foreach $i(@slist) {
- printf "%-20s : %5d\n",$i->[0],$i->[1];
- }
-} else { # If we ask for a specified server (by its name)
- my($flag) = 1;
- foreach $i(@slist) {
- if($i->[0] eq $sname) {
- printf "%-20s : %5d\n",$i->[0],$i->[1];
- $flag = 0;
- }
- }
- if($flag) { # If the server doesn't exist
- printf "The server [$sname] doesn't exist.\n";
- exit(1);
- }
-}
-
-# End of the software
-$so->shutdown(2);
-$so->close();
-exit(0);
-
-# Sub-function: get data from the socket
-sub soread {
- my($so,$len) = @_;
- my($sobuf);
- if(read($$so,$sobuf,$len) < $len) {
- print "Socket read error.\n";
- exit(5);
- }
- return $sobuf;
-};
diff --git a/tools/item_db.pl b/tools/item_db.pl
index 38ffe5d0a..1cbe2b9a3 100755
--- a/tools/item_db.pl
+++ b/tools/item_db.pl
@@ -65,6 +65,7 @@ while ($ligne=<STDIN>)
}
}
}
+print("\n");
sub printField {
diff --git a/tools/mapcheck.sh b/tools/mapcheck.sh
deleted file mode 100755
index 337884c43..000000000
--- a/tools/mapcheck.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/sh
-echo "============================================"
-echo "= map server status checker... ="
-echo "============================================"
-./map-server.exe &
-sleep 40
-
-while [ 0 ]
-do
- pcpu=` top -n 1| grep map-server | awk '{print $9}' | awk 'BEGIN{FS="."} {print $1}' `
- if [ "$pcpu" -gt 80 ];then
- echo "============================================"
- echo "map server is more than 80% (now $pcpu%)"
- echo "============================================"
- ppid=` ps -a | grep map-server | awk '{print $1}' `
- kill $ppid
- ./map-server.exe &
- sleep 40
- else
- pmapct=` ps -a| grep map-server | wc -l `
- if [ "$pmapct" -eq 0 ];then
- echo "============================================"
- echo "map server is not running..."
- echo "restart map server..."
- echo "============================================"
- ./map-server.exe &
- sleep 40
- #echo "test"
- else
- echo "map server is ok (now $pcpu%)..."
- sleep 5
- fi
- fi
-done \ No newline at end of file
diff --git a/tools/mapchecker.sh b/tools/mapchecker.sh
deleted file mode 100755
index 7250c342e..000000000
--- a/tools/mapchecker.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/bash
-
-athena_dir="/home/athena/658/"
-
-while [ true ] ; do
-
-if [ ` ps fauxw | grep map-server | grep -v grep | wc -l ` -eq 0 ];then
- #echo `date` " -- map-server crashed - restarting"
- echo `date` " -- map-server crashed - restarting" >> /var/log/athena_status.log
- killall -9 map-server
- cd $athena_dir
- nohup ./map-server ./conf/map_athena.conf ./inter_athena.conf &
- sleep 240
- #sleep 40 #for fast pc's remove the "#" at the beginning of the line and delete the line above
-fi
-
-
-if [ ` ps fauxw | grep map-server | grep -v grep | awk '{print $3}' | awk 'BEGIN{FS="."} {print $1}' ` -gt 10 ];then
- #echo `date` " -- mapserver cpuload over 10 - restarting"
- echo `date` " -- mapserver cpuload over 10 - restarting" >> /var/log/athena_status.log
- killall -9 map-server
- cd $athena_dir
- nohup ./map-server ./conf/map_athena.conf ./inter_athena.conf &
- sleep 240
- #sleep 40 #for fast pc's remove the "#" at the beginning of the line and delete the line above
- #echo `date` " -- restarted"
- echo `date` " -- restarted" >> /var/log/athena_status.log
-fi
-
-if [ ` ps fauxw | grep char-server | grep -v grep | wc -l ` -eq 0 ];then
- #echo `date` " -- char server crashed - restarting"
- echo `date` " -- char server crashed - restarting" >> /var/log/athena_status.log
- killall -9 char-server
- cd $athena_dir
- nohup ./char-server ./conf/char_athena.conf ./conf/inter_athena.conf &
- #echo `date` " -- restarted"
- echo `date` " -- restarted" >> /var/log/athena_status.log
-
-fi
-
-if [ ` ps fauxw | grep login-server | grep -v grep | wc -l ` -eq 0 ];then
- #echo `date` " -- login server crashed - restarting"
- echo `date` " -- login server crashed - restarting" >> /var/log/athena_status.log
- killall -9 login-server
- cd $athena_dir
- nohup ./login-server ./conf/login_athena.conf &
- #echo `date` " -- restarted"
- echo `date` " -- restarted" >> /var/log/athena_status.log
-
-fi
-
-
-#echo `date` " -- everything is fine"
-echo `date` " -- everything is fine" >> /var/log/athena_status.log
-sleep 30
-done
diff --git a/tools/mob_db.pl b/tools/mob_db.pl
index ebcf2b74b..38f851b73 100755
--- a/tools/mob_db.pl
+++ b/tools/mob_db.pl
@@ -95,6 +95,8 @@ while ($ligne=<STDIN>)
}
}
}
+print("\n");
+
sub printField {
my ($str, $suffix, $idCol) = @_;
diff --git a/vcproj-10/map-server_sql.vcxproj b/vcproj-10/map-server_sql.vcxproj
index d8a35698e..e3ad9f577 100644
--- a/vcproj-10/map-server_sql.vcxproj
+++ b/vcproj-10/map-server_sql.vcxproj
@@ -146,6 +146,7 @@
<ClInclude Include="..\src\map\atcommand.h" />
<ClInclude Include="..\src\map\battle.h" />
<ClInclude Include="..\src\map\battleground.h" />
+ <ClInclude Include="..\src\map\buyingstore.h" />
<ClInclude Include="..\src\map\chat.h" />
<ClInclude Include="..\src\map\chrif.h" />
<ClInclude Include="..\src\map\clif.h" />
@@ -168,6 +169,7 @@
<ClInclude Include="..\src\map\pet.h" />
<ClInclude Include="..\src\map\quest.h" />
<ClInclude Include="..\src\map\script.h" />
+ <ClInclude Include="..\src\map\searchstore.h" />
<ClInclude Include="..\src\map\skill.h" />
<ClInclude Include="..\src\map\status.h" />
<ClInclude Include="..\src\map\storage.h" />
@@ -195,6 +197,7 @@
<ClCompile Include="..\src\map\atcommand.c" />
<ClCompile Include="..\src\map\battle.c" />
<ClCompile Include="..\src\map\battleground.c" />
+ <ClCompile Include="..\src\map\buyingstore.c" />
<ClCompile Include="..\src\map\chat.c" />
<ClCompile Include="..\src\map\chrif.c" />
<ClCompile Include="..\src\map\clif.c" />
@@ -218,6 +221,7 @@
<ClCompile Include="..\src\map\pet.c" />
<ClCompile Include="..\src\map\quest.c" />
<ClCompile Include="..\src\map\script.c" />
+ <ClCompile Include="..\src\map\searchstore.c" />
<ClCompile Include="..\src\map\skill.c" />
<ClCompile Include="..\src\map\status.c" />
<ClCompile Include="..\src\map\storage.c" />
diff --git a/vcproj-10/map-server_txt.vcxproj b/vcproj-10/map-server_txt.vcxproj
index 3efded728..9a0b2bb0f 100644
--- a/vcproj-10/map-server_txt.vcxproj
+++ b/vcproj-10/map-server_txt.vcxproj
@@ -125,6 +125,7 @@
<ClCompile Include="..\src\map\atcommand.c" />
<ClCompile Include="..\src\map\battle.c" />
<ClCompile Include="..\src\map\battleground.c" />
+ <ClCompile Include="..\src\map\buyingstore.c" />
<ClCompile Include="..\src\map\chat.c" />
<ClCompile Include="..\src\map\chrif.c" />
<ClCompile Include="..\src\map\clif.c" />
@@ -148,6 +149,7 @@
<ClCompile Include="..\src\map\pet.c" />
<ClCompile Include="..\src\map\quest.c" />
<ClCompile Include="..\src\map\script.c" />
+ <ClCompile Include="..\src\map\searchstore.c" />
<ClCompile Include="..\src\map\skill.c" />
<ClCompile Include="..\src\map\status.c" />
<ClCompile Include="..\src\map\storage.c" />
@@ -174,6 +176,7 @@
<ClInclude Include="..\src\map\atcommand.h" />
<ClInclude Include="..\src\map\battle.h" />
<ClInclude Include="..\src\map\battleground.h" />
+ <ClInclude Include="..\src\map\buyingstore.h" />
<ClInclude Include="..\src\map\chat.h" />
<ClInclude Include="..\src\map\chrif.h" />
<ClInclude Include="..\src\map\clif.h" />
@@ -196,6 +199,7 @@
<ClInclude Include="..\src\map\pet.h" />
<ClInclude Include="..\src\map\quest.h" />
<ClInclude Include="..\src\map\script.h" />
+ <ClInclude Include="..\src\map\searchstore.h" />
<ClInclude Include="..\src\map\skill.h" />
<ClInclude Include="..\src\map\status.h" />
<ClInclude Include="..\src\map\storage.h" />
diff --git a/vcproj-6/map-server_sql.dsp b/vcproj-6/map-server_sql.dsp
index 629fe4639..63f41a468 100644
--- a/vcproj-6/map-server_sql.dsp
+++ b/vcproj-6/map-server_sql.dsp
@@ -231,6 +231,14 @@ SOURCE=..\src\map\battleground.h
# End Source File
# Begin Source File
+SOURCE=..\src\map\buyingstore.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\buyingstore.h
+# End Source File
+# Begin Source File
+
SOURCE=..\src\map\chat.c
# End Source File
# Begin Source File
@@ -411,6 +419,14 @@ SOURCE=..\src\map\script.h
# End Source File
# Begin Source File
+SOURCE=..\src\map\searchstore.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\searchstore.h
+# End Source File
+# Begin Source File
+
SOURCE=..\src\map\skill.c
# End Source File
# Begin Source File
diff --git a/vcproj-6/map-server_txt.dsp b/vcproj-6/map-server_txt.dsp
index 1359adc15..c7805649d 100644
--- a/vcproj-6/map-server_txt.dsp
+++ b/vcproj-6/map-server_txt.dsp
@@ -211,6 +211,10 @@ SOURCE=..\src\map\battleground.c
# End Source File
# Begin Source File
+SOURCE=..\src\map\buyingstore.c
+# End Source File
+# Begin Source File
+
SOURCE=..\src\map\chat.c
# End Source File
# Begin Source File
@@ -299,6 +303,10 @@ SOURCE=..\src\map\script.c
# End Source File
# Begin Source File
+SOURCE=..\src\map\searchstore.c
+# End Source File
+# Begin Source File
+
SOURCE=..\src\map\skill.c
# End Source File
# Begin Source File
@@ -335,6 +343,10 @@ SOURCE=..\src\map\battleground.h
# End Source File
# Begin Source File
+SOURCE=..\src\map\buyingstore.h
+# End Source File
+# Begin Source File
+
SOURCE=..\src\map\chat.h
# End Source File
# Begin Source File
@@ -427,6 +439,10 @@ SOURCE=..\src\map\script.h
# End Source File
# Begin Source File
+SOURCE=..\src\map\searchstore.h
+# End Source File
+# Begin Source File
+
SOURCE=..\src\map\skill.h
# End Source File
# Begin Source File
diff --git a/vcproj-7.1/map-server_sql.vcproj b/vcproj-7.1/map-server_sql.vcproj
index de441773c..15fb2ade2 100644
--- a/vcproj-7.1/map-server_sql.vcproj
+++ b/vcproj-7.1/map-server_sql.vcproj
@@ -167,6 +167,12 @@
RelativePath="..\src\map\battleground.h">
</File>
<File
+ RelativePath="..\src\map\buyingstore.c">
+ </File>
+ <File
+ RelativePath="..\src\map\buyingstore.h">
+ </File>
+ <File
RelativePath="..\src\map\chat.c">
</File>
<File
@@ -302,6 +308,12 @@
RelativePath="..\src\map\script.h">
</File>
<File
+ RelativePath="..\src\map\searchstore.c">
+ </File>
+ <File
+ RelativePath="..\src\map\searchstore.h">
+ </File>
+ <File
RelativePath="..\src\map\skill.c">
</File>
<File
diff --git a/vcproj-7.1/map-server_txt.vcproj b/vcproj-7.1/map-server_txt.vcproj
index f91248859..3ab9dbf0d 100644
--- a/vcproj-7.1/map-server_txt.vcproj
+++ b/vcproj-7.1/map-server_txt.vcproj
@@ -167,6 +167,12 @@
RelativePath="..\src\map\battleground.h">
</File>
<File
+ RelativePath="..\src\map\buyingstore.c">
+ </File>
+ <File
+ RelativePath="..\src\map\buyingstore.h">
+ </File>
+ <File
RelativePath="..\src\map\chat.c">
</File>
<File
@@ -302,6 +308,12 @@
RelativePath="..\src\map\script.h">
</File>
<File
+ RelativePath="..\src\map\searchstore.c">
+ </File>
+ <File
+ RelativePath="..\src\map\searchstore.h">
+ </File>
+ <File
RelativePath="..\src\map\skill.c">
</File>
<File
diff --git a/vcproj-8/map-server_sql.vcproj b/vcproj-8/map-server_sql.vcproj
index f1b1b6cd6..d09db6396 100644
--- a/vcproj-8/map-server_sql.vcproj
+++ b/vcproj-8/map-server_sql.vcproj
@@ -376,6 +376,14 @@
>
</File>
<File
+ RelativePath="..\src\map\buyingstore.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\map\buyingstore.h"
+ >
+ </File>
+ <File
RelativePath="..\src\map\chat.c"
>
</File>
@@ -556,6 +564,14 @@
>
</File>
<File
+ RelativePath="..\src\map\searchstore.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\map\searchstore.h"
+ >
+ </File>
+ <File
RelativePath="..\src\map\skill.c"
>
</File>
diff --git a/vcproj-8/map-server_txt.vcproj b/vcproj-8/map-server_txt.vcproj
index 4de699109..ddd430222 100644
--- a/vcproj-8/map-server_txt.vcproj
+++ b/vcproj-8/map-server_txt.vcproj
@@ -227,6 +227,14 @@
>
</File>
<File
+ RelativePath="..\src\map\buyingstore.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\map\buyingstore.h"
+ >
+ </File>
+ <File
RelativePath="..\src\map\chat.c"
>
</File>
@@ -407,6 +415,14 @@
>
</File>
<File
+ RelativePath="..\src\map\searchstore.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\map\searchstore.h"
+ >
+ </File>
+ <File
RelativePath="..\src\map\skill.c"
>
</File>
diff --git a/vcproj-9/map-server_sql.vcproj b/vcproj-9/map-server_sql.vcproj
index e147ca137..3e080b7e8 100644
--- a/vcproj-9/map-server_sql.vcproj
+++ b/vcproj-9/map-server_sql.vcproj
@@ -375,6 +375,14 @@
>
</File>
<File
+ RelativePath="..\src\map\buyingstore.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\map\buyingstore.c"
+ >
+ </File>
+ <File
RelativePath="..\src\map\chat.c"
>
</File>
@@ -555,6 +563,14 @@
>
</File>
<File
+ RelativePath="..\src\map\searchstore.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\map\searchstore.h"
+ >
+ </File>
+ <File
RelativePath="..\src\map\skill.c"
>
</File>
diff --git a/vcproj-9/map-server_txt.vcproj b/vcproj-9/map-server_txt.vcproj
index d4ea93a89..8edd0f411 100644
--- a/vcproj-9/map-server_txt.vcproj
+++ b/vcproj-9/map-server_txt.vcproj
@@ -226,6 +226,14 @@
>
</File>
<File
+ RelativePath="..\src\map\buyingstore.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\map\buyingstore.h"
+ >
+ </File>
+ <File
RelativePath="..\src\map\chat.c"
>
</File>
@@ -406,6 +414,14 @@
>
</File>
<File
+ RelativePath="..\src\map\searchstore.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\map\searchstore.h"
+ >
+ </File>
+ <File
RelativePath="..\src\map\skill.c"
>
</File>