diff options
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 @@ -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"> - © Content Copyright 2005 eAthena Development Team/Evera<br> - © 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"> - © Content Copyright 2005 eAthena Development Team/Evera<br> - © 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 <-- 100 = 1x drop rate, 1000 = 10x drop rate, etc<br />
+ item_rate_common_boss: 100 <--- drop rate for bosses<br />
+ item_drop_common_min: 1 <--- minimal drop rate<br />
+ item_drop_common_max: 10000 <--- 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"> - © Content Copyright 2005 eAthena Development Team/Evera<br> - © 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"> - © Content Copyright 2005 eAthena Development Team/Evera<br> - © 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"> - © Content Copyright 2005 eAthena Development Team/Evera<br> - © 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 Binary files differdeleted file mode 100644 index b11ea7dd9..000000000 --- a/readme/images/banner.gif +++ /dev/null diff --git a/readme/images/bg.gif b/readme/images/bg.gif Binary files differindex 20b046176..6c8c92c3b 100644 --- a/readme/images/bg.gif +++ b/readme/images/bg.gif diff --git a/readme/images/btmborder.gif b/readme/images/btmborder.gif Binary files differdeleted file mode 100644 index 116e49bb3..000000000 --- a/readme/images/btmborder.gif +++ /dev/null diff --git a/readme/images/btmborderbg.gif b/readme/images/btmborderbg.gif Binary files differdeleted file mode 100644 index 82a27195f..000000000 --- a/readme/images/btmborderbg.gif +++ /dev/null diff --git a/readme/images/chara.gif b/readme/images/chara.gif Binary files differdeleted file mode 100644 index 13b118a7a..000000000 --- a/readme/images/chara.gif +++ /dev/null diff --git a/readme/images/clown.png b/readme/images/clown.png Binary files differnew file mode 100644 index 000000000..55de4ba60 --- /dev/null +++ b/readme/images/clown.png diff --git a/readme/images/leftbg.gif b/readme/images/leftbg.gif Binary files differdeleted file mode 100644 index 0d4322919..000000000 --- a/readme/images/leftbg.gif +++ /dev/null diff --git a/readme/images/leftborder.gif b/readme/images/leftborder.gif Binary files differdeleted file mode 100644 index c139a9a5f..000000000 --- a/readme/images/leftborder.gif +++ /dev/null diff --git a/readme/images/logo.gif b/readme/images/logo.gif Binary files differdeleted file mode 100644 index 4f01126ec..000000000 --- a/readme/images/logo.gif +++ /dev/null diff --git a/readme/images/logobtm.gif b/readme/images/logobtm.gif Binary files differdeleted file mode 100644 index a80f6bc67..000000000 --- a/readme/images/logobtm.gif +++ /dev/null diff --git a/readme/images/rightbg.gif b/readme/images/rightbg.gif Binary files differdeleted file mode 100644 index bd5825593..000000000 --- a/readme/images/rightbg.gif +++ /dev/null diff --git a/readme/images/rightborder.gif b/readme/images/rightborder.gif Binary files differdeleted file mode 100644 index 88e27d304..000000000 --- a/readme/images/rightborder.gif +++ /dev/null diff --git a/readme/images/textbg.gif b/readme/images/textbg.gif Binary files differdeleted file mode 100644 index a092b75c1..000000000 --- a/readme/images/textbg.gif +++ /dev/null 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> Alberta - 100%</li></ul> - <ul><li> Al de Baran - 100%</li></ul> - <ul><li> Amatsu - 100%</li></ul> - <ul><li> Ayothaya - 75%</li></ul> - <ul><li> Comodo - 100%</li></ul> - <ul><li> Einbech - 90%</li></ul> - <ul><li> Einbroch - 75%</li></ul> - <ul><li> Geffen - 100%</li></ul> - <ul><li> Gonryun - 60%</li></ul> - <ul><li> Izlude - 100%</li></ul> - <ul><li> Louyang - 75%</li></ul> - <ul><li> Lutie - 100%</li></ul> - <ul><li> Morocc - 100%</li></ul> - <ul><li> Niflheim - 100%</li></ul> - <ul><li> Payon(New Maps) - 99%</li></ul> - <ul><li> Prontera - 100%</li></ul> - <ul><li> Umbala - 100%</li></ul> - - <li><strong>Job Quests</strong> (16/33)</li> - <ul><li> Novice Class (2/2)</li></ul> - <ul><ul><li> Novice - 100%</li></ul></ul> - <ul><ul><li> Super Novice - 100%</li></ul></ul> - <ul><li> 1-1 Class (6/6)</li></ul> - <ul><ul><li> Swordman - 100%</li></ul></ul> - <ul><ul><li> Mage - 100%</li></ul></ul> - - - <ul><ul><li> Archer - 100%</li></ul></ul> - - <ul><ul><li> Acolyte - 100%</li></ul></ul> - <ul><ul><li> Merchant - 100%</li></ul></ul> - <ul><ul><li> Thief - 100%</li></ul></ul> - <ul><li> 2-1 Class (6/6)</li></ul> - <ul><ul><li> Knight - 100%</li></ul></ul> - - <ul><ul><li> Priest - 100%</li></ul></ul> - <ul><ul><li> Wizard - 100%</li></ul></ul> - - <ul><ul><li> Blacksmith - 100%</li></ul></ul> - <ul><ul><li> Hunter - 100%</li></ul></ul> - - <ul><ul><li> Assassin - 100%</li></ul></ul> - - <ul><li> 2-2 Class (2/7)</li></ul> - <ul><ul><li> Crusader - 0%</li></ul></ul> - <ul><ul><li> Monk - 0% (Soon)</li></ul></ul> - <ul><ul><li> Sage - 0% (Soon)</li></ul></ul> - <ul><ul><li> Rogue - 100%</li></ul></ul> - - <ul><ul><li> Alchemist - 100%</li></ul></ul> - - <ul><ul><li> Bard - 0%</li></ul></ul> - <ul><ul><li> Dancer - 100%</li></ul></ul> - - <ul><li> 2-1-1 Class (0/6)</li></ul> - <ul><li> 2-2-1 Class (0/6)</li></ul> - <li><strong>Kafras</strong> - 100%</li> - - <li><strong>Guides</strong> - 100%</li> - - <li> <strong>War Of Emperium</strong> (4/5)</li> - <ul><li> Prontera - 100%</li></ul> - <ul><li> Geffen - 100%</li></ul> - - <ul><li> Payon - 100%</li></ul> - <ul><li> Al De Baran - 100%</li></ul> - - <ul><li> Novice - 0%</li></ul> - <li><strong>Quests</strong> (24/25)</li> - - <ul><li> Skill Quests (7/7)</li></ul> - - <ul><ul><li> Novice - 100%</li></ul></ul> - <ul><ul><li> Swordman - 100%</li></ul></ul> - <ul><ul><li> Mage - 100%</li></ul></ul> - <ul><ul><li> Archer - 100%</li></ul></ul> - <ul><ul><li> Acolyte - 100%</li></ul></ul> - <ul><ul><li> Merchant - 100%</li></ul></ul> - - <ul><ul><li> Thief - 100%</li></ul></ul> - - <ul><li>Town Quests (9/10)</li></ul> - <ul><ul><li> Prontera - 100%</li></ul></ul> - <ul><ul><li> Morocc - 100%</li></ul></ul> - <ul><ul><li> Geffen - 100%</li></ul></ul> - - <ul><ul><li> Izlude - 100%</li></ul></ul> - <ul><ul><li> Alberta - 100%</li></ul></ul> - <ul><ul><li> Al De Baran - 100%</li></ul></ul> - <ul><ul><li> Yuno - 100%</li></ul></ul> - - <ul><ul><li> Lutie - 100%</li></ul></ul> - <ul><ul><li> Comodo - 100%</li></ul></ul> - - <ul><ul><li> Payon - 20%</li></ul></ul> - <ul><li>Other Quests (9/9)</li></ul> - <ul><ul><li> Dye - 100%</li></ul></ul> - <ul><ul><li> MrSmile - 100%</li></ul></ul> - <ul><ul><li> Juice Making - 100%</li></ul></ul> - <ul><ul><li> Doomed Swords - 100%</li></ul></ul> - - <ul><ul><li> Bongun Taming - 100%</li></ul></ul> - - <ul><ul><li> Munak Taming - 100%</li></ul></ul> - <ul><ul><li> Tamking - 100%</li></ul></ul> - <ul><ul><li> Bongun Sword - 100%</li></ul></ul> - <ul><ul><li> The lvl 4 Weapon Quest - 100%</li></ul></ul> - <ul><li>Other (7/10)</li></ul> - <ul><ul><li> Card Remover - 100%</li></ul></ul> - - <ul><ul><li> PvP (old) - 100%</li></ul></ul> - <ul><ul><li> Time Arena - 100%</li></ul></ul> - <ul><ul><li> Bank - 100%</li></ul></ul> - - <ul><ul><li> Wedding - 80%</li></ul></ul> - - <ul><ul><li> Valkyrie - 10%</li></ul></ul> - - <ul><ul><li> Gefenia - 10%</li></ul></ul> - <ul><ul><li> Heal Npc - 100%</li></ul></ul> - <ul><ul><li> Warp Npc - 100%</li></ul></ul> - <ul><ul><li> Jobchange - 100%</li></ul></ul> - </ul> - - </td> - </tr> - <tr> - <td colspan="3"> - © Content Copyright 2005 eAthena Development Team/Evera<br> - © 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"> - © Content Copyright 2005 eAthena Development Team/Evera<br> - © 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 />
+ mes "[NPC Name]";<br>
+ mes "Hello World";<br>
+ close;<br>
+ }
+ </p>
+ <p>
+ <strong>Common Script Commands:</strong>
+ <ul>
+ <li><strong>mes</strong><br>
+ usage: mes "<message>";<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 "Close" button in an NPC's dialog window.
+ </li>
+ <li><strong>next</strong><br>
+ usage: next;<br>
+ info: displays a "Next" button in an NPC's dialog window.</li>
+ <li><strong>getitem</strong><br>
+ usage: getitem <item id>,<amount>;<br>
+ info: gives the player an item.
+ </li>
+ <li><strong>delitem</strong><br>
+ usage: delitem <item id>,<amount>;<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"> - © Content Copyright 2005 eAthena Development Team/Evera<br> - © 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> |